我有一项服务,该服务具有一种检查产品是否存在的方法。如果找到则返回true,否则返回false。但是,当我创建一个单元测试类并调用该方法时,即使该产品存在,它也总是返回false。当我运行该应用程序并使用邮递员进行测试时,它按预期工作,当发现其他情况为假时返回true。
服务类(当我通过控制器使用邮递员使用api时,按预期工作)
@Service
@Transactional
public class ProductService {
private ProductRepository productRepository;
@Autowired
public ProductService(ProductRepository productRepository) {this.productRepository = productRepository;}
//check if a product exists
public boolean checkIfProductExists(String name)
{
Product product = productRepository.findByName(name);
if(product != null)
{
return true;
}
return false;
}
}
测试
@RunWith(SpringRunner.class)
public class ProductServiceTests {
@MockBean
private ProductService productService;
@Test
public void checkIfProductExistsTest()
{
//result is supposed to be true because ARVs exists
//when i consume api using postman it returns true, but here false
//why is it always false no matter the input
boolean result = productService.checkIfProductExists("ARVs");
//therefore test fails but it is supposed to pass
assertEquals(true,result);
}
}
答案 0 :(得分:3)
您需要模拟productRepository
的响应
when(productRepository.findByName("ARVs")).thenReturn(myProduct);
答案 1 :(得分:2)
嘲笑ProductService
总是会导致false
。您应该做的是模拟ProductRepository
并将其注入ProductService
中。另外,如果要重现“ ARV”存在的情况,则应指示模拟。
@RunWith(SpringRunner.class)
public class ProductServiceTests {
@MockBean
private ProductRepository productRepository;
@Autowired
private ProductService productService;
@Test
public void checkIfProductExistsTest()
{
Product myProduct = new Product();
Mockito.when(productRepository.findByName("ARVs")).thenReturn(myProduct);
boolean result = productService.checkIfProductExists("ARVs");
assertEquals(true,result);
}
}
如果您不告诉模拟对象如何工作,则它将始终为对象返回null
,为false
变量返回boolean
。
答案 2 :(得分:2)
您正在对ProductService
进行单元测试,并且正在对它进行嘲笑。这不是单元测试的工作原理。
您嘲笑ProductService
的依赖性,在这种情况下为ProductRepository
。
因此,您的测试应该看起来像
@RunWith(SpringRunner.class)
public class ProductServiceTest {
@MockBean
private ProductRepository repository;
@Autowired
private ProductService productService;
@Test
public void test() {
Mockito.when(repository.findProductByName(Mockito.anyString())).thenReturn(new Product());
boolean result = productService.checkIfProductExists("some product name");
assertEquals(true, result);
}
@TestConfiguration
static class TestConfig {
@Bean
public ProductService productService(final ProductRepository repository) {
return new ProductService(repository);
}
}
}
答案 3 :(得分:1)
这种测试没有意义。我相信您本来打算检查ProductService
的代码,但是随后您为其创建了一个Mockito的模拟,默认情况下,无论使用任何参数调用checkIfProductxists
都会返回false。
如果您打算检查ProductService
-它不能是模拟的(使用@Autowired
而不是模拟bean`)。
您可能要考虑模拟存储库,以避免数据库调用。
因此,您应该@MockBean ProductRepository productRepository;
,然后对其进行注册:
@RunWith(SpringRunner.class) // you might need to supply some kind of context configuration here as well so that spring will know what beans should be really loaded
public class ProductServiceTest {
@Autowired ProductService productService;
@MockBean ProductRepository productRepo;
@Test
public void checkIfProductExistsTest() {
when(productRepo.findByName("ARVs")).thenReturn(<some_product_instance>);
boolean result = productService.checkIfProductExists("ARVs");
assertTrue(result);
}
}
答案 4 :(得分:1)
我认为您会在测试班级中寻找类似的东西:
@RunWith(SpringRunner.class)
public class ProductServiceTests {
@Autoired
private ProductService productService;
@MockBean ProductRepository productRepository;
@Test
public void checkTrueIfProductExists()
{
Product product = new Product();
Mockito.when(productRepository.findByName(Mockito.anyString())).thenReturn(product)
boolean result = productService.checkIfProductExists("foo");
assertTrue(result);
}
@Test
public void checkFalseIfProductDoesntExists()
{
Mockito.when(productRepository.findByName(Mockito.anyString())).thenReturn(null)
boolean result = productService.checkIfProductExists("bar");
assertFalse(result);
}
}
您之前将ProductService声明为模拟对象的事实实际上是我们确实希望将其连接起来然后模拟存储库。然后,我们可以使用Mockito之类的东西来控制存储库带回的结果。