【问题标题】:Mock a service of a service in another service Junit在另一个服务Junit中模拟一个服务的服务
【发布时间】:2017-09-19 06:02:05
【问题描述】:

我有以下服务:

@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();
            }
        }
    }

【问题讨论】:

  • 对于受保护的 ClientService 客户端服务,您不需要 @Autowired;也代替受保护的ClientService clientService;尝试使用 - private ClientServiceImpl clientService
  • ContractService 的 getInfo 也不可见。你能添加那个方法吗?
  • @asg 添加了方法
  • 整个过程会简单很多,如果你在你的服务中使用构造器注入,你可以完全消除Spring。
  • 当您告诉 Mockito 期望 DocumentInfo 对象用于 getInfo() 方法时,您的 Test 类中是否存在编译问题,但实际上它接受 String?在这行代码when(this.contractService.getInfo(multipartFile)).thenReturn(multipartFile)

标签: java spring junit mockito


【解决方案1】:

我认为您与 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) 意味着所有对象的创建都无需您进行任何进一步的工作。

【讨论】:

  • 之前尝试过。还是没有运气!
  • 我添加了一个更大的示例:删除 Autowired,并添加了一个 Runwith。这对我有用
【解决方案2】:

@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】:
         DocumentInfo multipartFile = new DocumentInfo();
         multipartFile.setMultipartFileId(1234);
         when(this.contractService.getInfo(multipartFile)).thenReturn(multipartFile);
    

    在这里,您希望模拟中出现 multipartFile 实例,但事实并非如此,因为在测试期间会有另一个 DocumentInfo 实例(请参阅创建它的 getInfo 方法)。

    你应该改变你的模拟是这样的:

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

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

    【讨论】:

      【解决方案4】:

      根本原因:您没有将 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 应用同样的方法

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-17
        • 1970-01-01
        • 2018-10-15
        • 2021-08-30
        • 2013-12-22
        相关资源
        最近更新 更多