首页 > 解决方案 > 将存储库的模拟注入服务不会注入正确的模拟方法(Spring、JUnit 和 Mockito)

问题描述

tl;dr:似乎我使用自定义行为创建的存储库的 Mock 关于注入时保存方法的自定义行为丢失了自定义行为。


问题描述

我一直在尝试在 Spring 中测试服务。特别感兴趣的方法采用一些参数并创建一个用户,该用户通过存储库方法save保存到UserRepository中。

我感兴趣的测试是将这些参数与传递给存储库的保存方法的用户属性进行比较,并以这种方式检查它是否正确添加了新用户。

为此,我决定模拟存储库并将相关服务方法传递的参数保存到存储库保存方法。

我基于这个问题来保存User

private static User savedUser;

public UserRepository createMockRepo() {
   UserRepository mockRepo = mock(UserRepository.class);
   try {
      doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                savedUser= (User) invocation.getArguments(0);
                return null;
            }
        }).when(mockRepo).save(any(User.class));
   } catch( Exception e) {}
   return mockRepo;
}

private UserRepository repo = createMockRepo();

两个注意事项:

然后我创建了一个测试函数来检查它是否具有所需的行为并且一切都很好。

@Test 
void testRepo() {
   User u = new User();
   repo.save(u);
   assertSame(u, savedUser);
}

然后,我尝试按照我在多个问题中看到的建议进行操作,即将模拟注入到服务中,如此所述。

@InjectMocks
private UserService service = new UserService();

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

这就是问题出现的地方,当我尝试访问savedUser属性时,我为它创建的测试抛出了一个空异常(这里我简化了 users 属性,因为这似乎不是原因)。

@Test 
void testUser() {
   String name = "Steve";
   String food = "Apple";
   
   service.newUser(name, food);

   assertEquals(savedUser.getName(), name);
   assertEquals(savedUser.getFood(), food);
}

调试时:

出于演示目的,我决定使用System.out.println记录该函数。

我的测试记录打印,表明用户测试没有调用answer方法


我在这里做错了什么?

提前感谢您的帮助,这是我的第一个堆栈交换问题,非常感谢任何改进提示。

标签: javaspringunit-testingjunitmockito

解决方案


不要像您那样在测试类中实例化您的服务,而是使用 @Autowired 并确保您的 UserRepository 在测试类中有 @MockBean

@InjectMocks
@Autowired
private UserService service

@MockBean
private UserRepository mockUserRepo

有了这个,你可以删除你的设置方法

但请确保您的 UserRepository 也在您的服务内部自动装配


推荐阅读