English 中文(简体)
测试无效方法
原标题:Testing the behavior of void method

附录一

public class UserService {

    @Autowired
    private UserDao dao;

    public void addUser(String username, String password) {
        if (username.length() < 8 ) {
            username = username  + "random" ; // add some random string
        }
        User user = new User(username, password);

        dao.save(user);
    }
}

当用户名长度少于8年,用户名超过8个时,我想测试“替代用户”方法的行为。 如何在单位测试用户服务。 我知道的是用断言(......),但“密码”在添加User(......)方法之外没有。

I use JUnit and Mockito.

最佳回答

在几个月后再次审议这一问题之后,我提出了解决办法。

设想是观察向用户Dao发送的物体用户。 我们可以通过这样做来检查用户名称的价值,因此单位测试代码:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
    @Mock
    private UserDao dao;

    @InjectMock
    private UserService service;

    @Test
    public void testAddingUserWithLessThan8CharUsername () {
        final String username = "some";
        final String password = "user";
        doAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
                Object[] args = invocationOnMock.getArguments();
                User toBeSaved = (User) args[0];
                Assert.assertEquals(username + "random", toBeSaved.getPassword());
                return null;
            }
        }).when(userDao).save(Matchers.any(User.class));
        service.addUser(username, password);
    }
}

纪尧姆实际上答案最接近,但他用大米回答。 然而,他向我提出了如何做到这一点的想法,因此我认为他也值得一些赞扬。

问题回答

Use a mocking framework. The example below uses JMock2, but it would be similar with EasyMock, Mockito, etc. Also, you need to extract the username generation to something like UsernameGenmerator to be able to mock it. You need another specific test for the username generator.

private final Mockery mockery = new Mockery();
private final UserDao mockDao = mockery.mock(UserDao.class);
private final UsernameGenerator mockUserNameGenerator = mockery.mock(UsernameGenerator.class);

@Test 
public void addUserUsesDaoToSaveUser() {
    final String username = "something";
    final String generatedUsername = "siomething else";
    final String password = "a password";
    mockery.checking(new Expectations() {{
        oneOf(mockUsernameGenerator).generateUsername(username);
        will(returnValue(generatedUsername));
        oneOf(mockDao).save(new User(generatedUsername, password)); // assumes your User class has a "natueral" equals/hashcode
    }});

    UserService userService = new UserService();
    userService.addUser(username, password);
}

UsernameGenerator 您需要测试回归用户名称的长度:

@Test 
public void leavesUsernameUnchangedIfMoreThanEightChars() {
    final String username = "123456789";
    final UsernameGenerator usernameGenerator = new UsernameGenerator();
    assertEquals(username, userGenerator.generateUsername(username));
}

@Test 
public void addsCharactersToUsernameIfLessThanEightChars() {
    final String username = "1234567";
    final UsernameGenerator usernameGenerator = new UsernameGenerator();
    assertEquals(8, userGenerator.generateUsername(username).length());
}

当然,根据你的“统治”方法,你可能要测试自己的具体行为。 除此以外,以上为你的法典提供了充分的覆盖面。

Consider extracting user name generation logic as dependency from UserService.

interface UserNameGenerator {
    Strign generate();
}

。 并将守则改为:

public class UserService {

    @Autowired
    private UserDao dao;
    @Autowired
    private UserNameGenerator nameGenerator;

    public void addUser(String username, String password) {
        if (username.length() < 8 ) {
            username = nameGenerator.generate();
        }
        User user = new User(username, password);

        dao.save(user);
    }
}

其次产生<代码>的违约执行。 用户名称生成逻辑

现在,你可以通过模拟<代码>UserNameGenerator和UserDao轻易检查行为。

用户名下限时检查使用情况

String username = "123";
String password = "pass";

String generatedName = "random";

// stub generator
when(nameGenerator.generate()).thenReture(generatedName);

// call the method
userService.addUser(username, password);

// verify that generator was called
verify(nameGenerator).generate();

verify(userDao).save(new User(generatedName, password));

用户名称长度大于8时核对使用情况

String username = "123456789";
String password = "pass";

String generatedName = "random";

// call the method
userService.addUser(username, password);

// verify that generator was never called
verify(nameGenerator, never()).generate();

verify(userDao).save(new User(username, password));

最容易的方法是摘取贵国对用户名称更正逻辑的部分。

if (username.length() < 8 ) {
    username = username  + "random" ; // add some random string
}

采用这种方法并测试这种方法的回报价值。

public string GetValidUsername(string userName){
    if (username.length() < 8 ) {
        return username  + "random" ; // add some random string
    }
    return username;
}

with this you can pass different types of username and test the behavior of your code.





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...