在另一个服务Junit中模拟服务服务

时间:2017-09-19 06:02:06

标签: java spring junit mockito

我有以下服务:

@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    protected ContractService contractService;

    private void saveInCache(MultipartFile multipartFile) {
        this.contractService.saveInCache(multipartFile);
    }
}

和另一项服务

@Service
public class ClientServiceImpl implements ClientService {

    @Autowired
    protected ContractService contractService;

    private void getInfoOfFile(String multipartFileId) {
        DocumentInfo document = this.contractService.getInfo(multipartFileId);
        ///
    }
}

我有我的Junit

public class ClientControllerTest extends ApiWebTest {

  @Mock
  protected ContractService contractService;

  @Autowired
  @InjectMocks
  protected ClientService clientService = new ClientServiceImpl();

  @Before
  private void setup() {
     MockitoAnnotations.initMocks(this);
  }

  @Test
  private void testGetInfo() {
     // Code
     DocumentInfo multipartFile = new DocumentInfo();
     multipartFile.setMultipartFileId(1234);
     when(this.contractService.getInfo(multipartFile.getMultipartFileId())).thenReturn(multipartFile);

   // Test the Client service 'getInfoOfFile' method.
  }
}

当我在调试模式下运行此测试时,我发现this.contractService.getInfo(multipartFileId);正在返回'null'。

我在嘲笑中出错了。

我刚刚在JUnit中模拟了ContractService。我是否还需要模拟AccountServiceImpl?

编辑:添加saveInCache和getInfo方法

private DocumentInfo getInfo(String documentId) {
        if (StringUtils.isEmpty(documentId)) {
            return null;
        }
        WriteLock lock = this.readWriteLock.writeLock();
        try {
            lock.lock();
            DocumentInfo cachedDocument = this.documentCache.get(documentId);
            return cachedDocument;
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }
    }

private DocumentInfo saveInCache(StreamingStorage document) {
        if (document == null) {
            throw new InvalidParameterException("Creative document is required to put into cache.");
        }
        WriteLock lock = this.readWriteLock.writeLock();
        try {
            lock.lock();
            DocumentInfo newCachedDocument = this.documentCache.put(document.getDocumentId(), document);
            return newCachedDocument;
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }
    }

4 个答案:

答案 0 :(得分:1)

根本原因:您没有将ContractService注入ClientService。

我认为您可以使用 ReflectionTestUtils 更轻松地解决问题。这意味着您会将模拟的ContractService注入AccountServiceImpl。

public class ClientControllerTest extends ApiWebTest {
  protected ClientService clientService = new ClientServiceImpl();
  private ContractService contractService;
  @Test
  private void testGetInfo() 
  {
     // Code
     DocumentInfo multipartFile = new DocumentInfo();
     multipartFile.setMultipartFileId(1234);
     contractService= EasyMock.createNiceMock(ContractService.class);
     ReflectionTestUtils.setField(clientService, "contractService", contractService);
     EasyMock.expect(contractService.getInfo(multipartFile.getMultipartFileId())).andReturn(multipartFile).anyTimes();
     EasyMock.replay(contractService);
  }
}

您可以将其应用于JUnit

答案 1 :(得分:0)

我认为你与clientService的声明相矛盾。

你有:

@Autowired
@InjectMocks
protected ClientService clientService = new ClientServiceImpl();

这应该创建一个名为clientService的自动装配ClientService并注入模拟。然而,= new ClientServiceImpl()将覆盖自动装配并创建一个普通的香草(我想!)。同时也不需要@Autowired@InjectMocks - 您希望创建一个注入了模拟的服务 - 而不是自动装配的对象。

你可以试着像这样改变你的测试:

@RunWith(MockitoJUnitRunner.class)
public class ClientControllerTest extends ApiWebTest {

  @Mock
  protected ContractService contractService;

  @InjectMocks
  protected ClientService clientService;

  @Test
  private void testGetInfo() {
     DocumentInfo multipartFile = new DocumentInfo();
     multipartFile.setMultipartFileId(1234);
     when(this.contractService.getInfo(multipartFile)).thenReturn(multipartFile);

  }
}

添加@RunWith(MockitoJUnitRunner.class)意味着无需任何进一步的工作就可以创建所有对象。

答案 2 :(得分:0)

@InjectMocks创建该类的实例,并将使用@Mock注释创建的模拟注入其中。因此,您不必创建ClientService实例,并在其上删除@Autowired

您可以使用MockitoJUnitRunner代替MockitoAnnotations.initMocks(this)。代码更简单。

更改后的测试类:

@RunWith(MockitoJUnitRunner.class)
public class ClientControllerTest extends ApiWebTest {

    @Mock
    private ContractService contractService;

    @InjectMocks
    private ClientService clientService;

    @Test
    private void testGetInfo() {
       // Code
       DocumentInfo multipartFile = new DocumentInfo();
       multipartFile.setMultipartFileId(1234);

       when(this.contractService.getInfo(multipartFile)).thenReturn(multipartFile);

       // Test the Client service 'getInfoOfFile' method.
    }
}

答案 3 :(得分:0)

     DocumentInfo multipartFile = new DocumentInfo();
     multipartFile.setMultipartFileId(1234);
     when(this.contractService.getInfo(multipartFile)).thenReturn(multipartFile);

在这里,您希望模拟中的multipartFile实例不是这种情况,因为在测试期间会有另一个DocumentInfo实例(请参阅创建它的getInfo方法)。 / p>

您应该将模拟更改为:

 when(this.contractService.getInfo(any())).thenReturn(multipartFile);

在这种情况下,期望将与DocumentInfo的任何实例匹配,而不是您通过构造函数multipartFile = new DocumentInfo();创建的特定实例