Sunday, September 20, 2015

Java Test Framework



https://asolntsev.github.io/en/2016/04/11/unit-tests-with-java8/
public Employee(Consumer<Employee> builder) {
  builder.accept(this);
}
Also you can achieve similar behaviour using java initializer block:

class User {
String name;
}

User user = new User() {{name = "Mock username";}};
There are some recommendations to avoid using "initializer block" in Java. One of reasons is that it can cause memory leaks, because the anonymous class has hidden reference to the caller.
PowerMock
https://github.com/powermock/powermock/wiki/Mockito-2-(Maven)

https://github.com/jayway/powermock/wiki/MockitoUsage
https://blog.codecentric.de/en/2011/11/testing-and-mocking-of-static-methods-in-java/
@RunWith(PowerMockRunner.class)
@PrepareForTest( MathUtil.class )
public class CalculatorTest {
 
   /** Unit under test. */
   private Calculator calc;
 
   @Before public void setUp() {
      calc = new Calculator();
 
      PowerMockito.mockStatic(MathUtil.class);
      PowerMockito.when(MathUtil.addInteger(1, 1)).thenReturn(0);
      PowerMockito.when(MathUtil.addInteger(2, 2)).thenReturn(1);
   }
 
   @Test public void shouldCalculateInAStrangeWay() {
      assertEquals(0, calc.add(1, 1) );
      assertEquals(1, calc.add(2, 2) );
   }
}
With the@PrepareForTest( MathUtil.class ) annotation our class to mock is prepared. This annotation takes a list of all the classes to mock. In our example, this list consists of a single item MathUtil.class.
http://stackoverflow.com/questions/25763338/capture-parameters-passes-to-stub-in-powermockito
After the call to verifyStatic, you'll need to actually call the method you're trying to verify, as inthe documentation here:
PowerMockito.verifyStatic();
Static.thirdStaticMethod(Mockito.anyInt());
At that point you can use Mockito argument captors, as demonstrated (but not tested):
ArgumentCaptor<Properties> propertiesCaptor =
    ArgumentCaptor.forClass(Properties.class);

PowerMockito.verifyStatic();
SomeStaticClass.methodBeingStubbed(propertiesCaptor.capture());

Properties passedInValue = propertiesCaptor.getValue();
If you're used to @Mock annotations, or you need to capture a generic (as in List<String>), you may also be interested in using the @Captor annotation instead.
hamcrest
https://www.javaworld.com/article/2074689/core-java/hamcrest-containing-matchers.html
The just-discussed hasItem() and hasItems() matchers are less strict than contains() and even less strict than containsInAnyOrder() and are often what one wants when one wants to simply ensure that one or multiple items are somewhere in a collection without concern about the item's order in that collection or that other possible items are in that collection.


assertThat("Groovy", isIn(strings));

  • Ensure that the Hamcrest JAR is on the test classpath before the JUnit JAR.
  • Use contains when you want to ensure that the collection contains all specified items and no other items and you want the collection to contain the items in the specified order.
    • Generally avoid using contains() matcher with Sets because they are unordered by nature.
  • Use containsInAnyOrder matcher when you still want to strictly test for presence of exactly same items in collection as specified in test, but don't care about the order (applicable for Sets).
  • Use hasItem() and hasItems() matchers to ask a collection if it contains, possibly among other unlisted items and in no particular order, the specified item or items.
  • Use isIn() matcher to ask if a particular item is in the specified collection with no regard for whether other items are in that collection or what order that item is in within the containing collection.
https://objectpartners.com/2013/09/18/the-benefits-of-using-assertthat-over-other-assert-methods-in-unit-tests/
Readability
assertThat(actual, is(equalTo(expected)));
assertThat(actual, is(expected));
assertThat(actual, is(not(expected)));

Better Failure Messages
assertThat

assertThat(actual, is(equalTo(expected)));
Better Failure Messages
assertThat(actual, containsString(expected));

Type Safety
assertThat(123, is("abc")); //does not compile

assertThat("test", anyOf(is("test2"), containsString("te")));
assertThat(actual, nullValue());
assertThat(actual, notNullValue());

assertThat(actual, sameInstance(expected));
assertThat(actual, not(sameInstance(expected)));

http://www.vogella.com/tutorials/Hamcrest/article.html
        assertThat(list, hasSize(3));
        // ensure the order is correct
        assertThat(list, contains(5, 2, 4));
        assertThat(list, containsInAnyOrder(2, 4, 5));
        assertThat(list, everyItem(greaterThan(1)));

// Check that a list of objects has a property race and
// that the value is not ORC
assertThat(fellowship, everyItem(hasProperty("race", is(not((ORC))))));

assertThat("test", anyOf(is("testing"), containsString("est")));

  • allOf - matches if all matchers match (short circuits)
  • anyOf - matches if any matchers match (short circuits)
  • not - matches if the wrapped matcher doesn’t match and vice
  • equalTo - test object equality using the equals method
  • is - decorator for equalTo to improve readability
  • hasToString - test Object.toString
  • instanceOfisCompatibleType - test type
  • notNullValuenullValue - test for null
  • sameInstance - test object identity
  • hasEntryhasKeyhasValue - test a map contains an entry, key or value
  • hasItemhasItems - test a collection contains elements
  • hasItemInArray - test an array contains an element
  • closeTo - test floating point values are close to a given value
  • greaterThangreaterThanOrEqualTolessThanlessThanOrEqualTo
  • equalToIgnoringCase - test string equality ignoring case
  • equalToIgnoringWhiteSpace - test string equality ignoring differences in runs of whitespace
  • containsStringendsWithstartsWith - test string matching
assertThat(todo, hasProperty("summary", equalTo("Learn Hamcrest")));
Todo todo1 = new Todo(1, "Learn Hamcrest", "Important");
Todo todo2 = new Todo(1, "Learn Hamcrest", "Important");

assertThat(todo1, samePropertyValuesAs(todo2));

assertThat(stringToTest, isEmptyOrNullString());
assertThat(stringToTest, isEmptyString());
http://stackoverflow.com/questions/1092219/assertcontains-on-strings-in-junit
assertThat(person.getName(), containsString("myName"));

assertThat("my error message", person.getName(), containsString("myName"));

        assertThat(movie.getTitle(), containsString("Angels"));
        // Checks that the actual result starts with the specified String
        assertThat(movie.getTitle(), startsWith("Charlies"));
        // Checks that the actual result ends with the specified String
        assertThat(movie.getTitle(), endsWith("Angels"));
        // Checks that the actual result equals the specified String, ignoring casing
        assertThat(movie.getTitle(), equalToIgnoringCase("charlies angels"));
        // Beware: this method work different than you would expect, 
since it doesn't ignore whitespaces: it ignores most of them. Check the Javadoc.
        assertThat(movie.getTitle(), equalToIgnoringWhiteSpace(" charlies  angels   "));
        // Checks that the actual result is an empty String
        assertThat(movie.getDescription(), isEmptyString());
        // Checks that the actual result is null or an empty String
        assertThat(movie.getDirector(), isEmptyOrNullString());
        // Checks that the actual result contains the specified Strings in this sequence
        assertThat(movie.getStoryLine(), stringContainsInOrder(Arrays.asList("The", "trio", "arts")));

BDD
http://www.hascode.com/2014/12/bdd-testing-with-cucumber-java-and-junit/
JBehave
JBehave BDD – How to get Started using the Eclipse jBehave Plugin
https://blog.codecentric.de/en/2012/06/jbehave-configuration-tutorial/
http://fazlansabar.blogspot.com/2013/06/jbehave-tutorial-bdd-framework-for.html
IMPORTANT NOTE: By default, jBehave framework will look for *.story files defined in the same package as the corresponding *Stories.java file.

The following contains a simple user story for adding two numbers, which is defined in org/fazlan/jbehave/exmaple/stories/calculator_stories.story

 Narrative:  
 In order to quickly find out the sum of two numbers  
 As a user  
 I want to use a calculator to add two numbers
  
 Scenario: Add two valid numbers
  
 Given a calculator  
 When I add <number1> and <number2>  
 Then the outcome should <result>
  
 Examples:  
 |number1|number2|result|  
 |10|10|20| 

public class AddTwoNumbersSteps {  

   private Calculator calculator;  

   @Given("a calculator")  
   public void givenACalculator() {  
     calculator = new Calculator();  
   }  

   @When("I add <number1> and <number2>")  
   public void whenIAddNumber1AndNumber2(@Named("number1")int number1, @Named("number2")int number2) {  
     calculator.add(number1, number2);  
   }  

   @Then("the outcome should <result>")  
   public void thenTheOutcomeShould(@Named("result")int result) {  
     assert calculator.getResult() == result;  
   }  
 }  
Web UI Integration Test
Selenium WebDriver

TESTING SYSTEM.OUT.PRINTLN OUTPUTS
        PrintStream out = mock(PrintStream.class);
        System.setOut(out);
        App.main(new String[]{});
        verify(out).println(startsWith("Use:"));



浅谈jmockit中mock机制的实现
在jmockit中,你可以使用MockUp来创建一个“fake”的实例,对某个方法指定自己的实现,而不是调用实际的方法。
对于接口类型,需要这样调用:
@Mocked
private SomeInterface mockInstance;

mockInstance = new MockUp<SomeInteface>() {
    ...
}.getMockInstance();
这个倒没有什么古怪的。估计又是使用了java.reflect.Proxy。这个技巧在很多Java框架中用到,比如Spring AOP对于接口类型的实现,就是通过Proxy来混入拦截器实现的。
但是,对于其他类型的调用,就比较奇怪了:
@Mocked
private SomeProxy mockInstance;

new MockUp<SomeProxy>() {
    @Mock
    public int doSth() {
        return 1;
    }
};

mockInstance.doSth(); // return 1
new出来的对象,如果没有赋值给新的变量,应该是随着GC风飘云散了。可就是在我的眼皮底下,mockInstance就这样被掉包了。
Spring AOP中,对于非接口类型,是通过CGLIB魔改字节码来实现拦截器注入的。所以我估计这个也是一样的道理。不过令人想不通的是,jmockit到底是什么时候进行移花接木的


众所周知,Java代码先是编译成class文件,然后由JVM加载运行的。围绕JVM这一中间层,各种有趣的技术应运而生。比如各种类加载器,可以动态地去加载同名的类的不同实现(不同的class文件)。还有各种魔改class文件的手段,在原来的实现中注入自己的代码,像ASM、javassist、GCLIB,等等。jmockit就是应用ASM来修改原来的class文件,用mocked的实现掉包原来的代码。因为MockUp的构造已经触发了“狸猫换太子”的幕后行为,所以这里就不用把new出来的东西赋值给具体变量了。
还有一个问题。我们虽然弄明白了jmockit的作案手法,可是还没有找到掉包现场呢!即使现在jmockit已经持有了被篡改后的字节码,可它又是怎么替换呢?
继续看下去,发现jmockit把修改后的字节码存在StartUp.java里面了。转过去会看到,jmockit这里用到了JDK6的一个新特性:动态Instrumentation。怪不得jmockit要求JDK版本知识在6以上。
关于动态Instrumentation,具体可以看下这篇文章:http://www.ibm.com/developerworks/cn/java/j-lo-jse61/
简单来说,通过这一机制可以实现监听JVM加载类的事件,并在此之前运行自己的挂钩方法。这么一来,掉包现场也找到了。
那jmockit怎么知道要监听哪些类呢?前面可以看到,需要Mock的类上,要添加Mocked注解。所以jmockit编写了一些跟主流测试框架集成的代码,在测试运行的时候获取带该注解的类。这样就知道要监听的目标了。
总结一下:jmockit先通过Mocked注解标记需要Mock掉的类。然后调用new MockUp去创建修改后的class文件。在JVM运行的时候,通过JDK6之后的动态Instrumentation特性监听类加载事件,并在目标类加载之前移花接木,用魔改后的字节码换掉真货。虽然Java是门静态类型语言,不过幸亏有字节码和JVM作为中间层,使得mock实现起来相对容易。
https://dzone.com/articles/anatomy-of-a-good-java-test
There is in fact a great IntelliJ plugin called Enso which will turn your test names into sentences which appear next to each class so you can see exactly what you’re doing.

Never start a test name with “test”. This is a hangover from the early days of JUnit when it was needed to execute. Your Test class is going to be in the Test folder, in a class which has the word Test at the end. It will have an @Test annotation on it. We know it’s a test.

You should also avoid starting with “should” or “will”. These are noise words. You’ve written a test for this functionality, we know it should/will work (or, if it doesn’t, we know we need to fix it).
Don’t be afraid to be expressive. If your test name needs to be really long then go for it if it’s clear what’s going on.

  • Move generic setup to a specific setup method using the @Before annotation.
  • Move repeated setup code into helper methods
  • User a Maker to create complex test objects and only set the relevant values in your te
Again, ideally, we want to have a solitary assertion. This makes it clear what we are testing and shows that our code doesn’t have side effects. Like everything in this article this is not a hard rule as there are cases when it will be necessary, but if you have a test like this:
        assertThat(orderBook.bids.size(), is(4));
        assertThat(orderBook.asks.size(), is(3));
        assertThat(orderBook.bids.get(0).price, is(5200));
        assertThat(orderBook.asks.get(2).price, is(10000000));
        assertThat(orderBook.asks.get(2).isBuy, is(false));
It becomes much harder to understand where a test has failed or which assertion is important.
It is possible to write custom matchers in Hamcrest which can provide an elegant solution to complex assertions. If you need to run assertions in a loop, or you have a large number of fields to assert on, a custom matcher could be the way to go.
  • Ensure it’s clear why the values you're comparing against are why they are. For example, if you’re comparing a field value to the number 3000, why is it 3000? This should be painfully clear. Obviously don’t use a magic number and ensure the variable is well named to show how its value is derived.
http://www.mkyong.com/unittest/junit-4-vs-testng-comparison/
@RunWith(Suite.class)
@Suite.SuiteClasses({
        JunitTest1.class,
        JunitTest2.class
})
public class JunitTest5 {
}

The “@RunWith” and “@Parameter” is use to provide parameter value for unit test, @Parameters have to return List[], and the parameter will pass into class constructor as argument.
Java
@RunWith(value = Parameterized.class)
public class JunitTest6 {
 
  private int number;
 
  public JunitTest6(int number) {
     this.number = number;
  }

  @Parameters
  public static Collection<Object[]> data() {
    Object[][] data = new Object[][] { { 1 }, { 2 }, { 3 }, { 4 } };
    return Arrays.asList(data);
  }
  
  @Test
  public void pushTest() {
    System.out.println("Parameterized Number is : " + number);
  }
}
 i suggest to use TestNG as core unit test framework for Java project, because TestNG is more advance in parameterize testing, dependency testing and suite testing (Grouping concept). TestNG is meant for high-level testing and complex integration test. Its flexibility is especially useful with large test suites. In addition, TestNG also cover the entire core JUnit4 functionality.

http://blog.socosomi.com/dont-prefix-your-test-names-with-test/
Please don’t start every JUnit test method name with the word “test“.
@Test
public void testParsingAnEmptyStringShouldReturnAnEmptyDocument();
I know JUnit used to require this convention in order to figure out which methods to run. That was before JUnit4 came out… 6 years ago. There is no need to include it any more.
@Test
public void parsingAnEmptyStringShouldReturnAnEmptyDocument();
We know it is a test from the @Test annotation just before it. Having every test method start with “test” is about as useful as having every method start with “method“. If everyone has it, there is no need to have it at all. The same goes for other prefixes, such as “verify“.


























The same goes for the setUp() and tearDown() methods of JUnit 3. Now, we use @Before and@After instead, so please tell me what the method is doing instead.
@Before
public void initializeObjectDatabase();
@After
public void releaseFileHandles();

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts