I have got question connected with google test. I would like to ask if while inducing "EXPECT_CALL(*A, some_method(mes1));" in test case there is possiblity to compare fields included
in mes1 class.
struct Mes
{
int a;
};
//short section of test case:
Mes mes1 = Mes();
EXPECT_CALL(*A, some_method(mes1));
I would like to ask if in google mock is a possiblity to compare special fields included in Mes. Something like:
EXPECT_CALL(*A, some_method(mes1), compare(Mes.a));//in this case google mock would compare only field "a" from Mes.
It depends on what you want to do with the result of the comparison. If you simply want to query the value of the field, you can simply define a function to do something with it:
// Note: The signature of someFunction needs to match some_method.
void someFunction(const Mes& mes)
{
// Do something with mes.a
}
Then set up your expectation as follows:
EXPECT_CALL(*A, some_method(mes1)).WillOnce(Invoke(someFunction));
Note that if some_method returns a value, you may also have to provide a Return action.
Alternatively, if you want your test to fail if the field isn't some specific value, you need to write a custom matcher:
MATCHER_P(MesFieldEq, val, "")
{
return (arg.a == val);
}
Then use it in your expectation as follows:
// Fails unless mes.a is equal to 42.
EXPECT_CALL(*A, some_method(MesFieldEq(42));
Related
I have a method that among others generates an identifier, sends it to some external dependency and returns it. I want to have a unit test that tests if the same value that was sent there is returned.
Let's say that the test and the code look like this:
def "test"() {
given:
def testMock = Mock(TestMock)
and:
def x
when:
def testClass = new TestClass()
x = testClass.callMethod(testMock)
then:
1 * testMock.method(x)
}
static interface TestMock {
void method(double x)
}
static class TestClass {
double callMethod(TestMock mock) {
double x = Math.random()
mock.method(x)
return x
}
}
The code works correct, however the test fails with a message:
One or more arguments(s) didn't match:
0: argument == expected
| | |
| | null
| false
0.5757686318956925
So it looks like the mock check in then is done before the value is assigned in when block.
Is there a way to make Spock assign this value before he checks the mock call? Or can I do this check in a different way?
The only idea I have is to inject an id-generator to the method (or actually to the class) and stub it in the test, but it would complicate the code and I would like to avoid it.
I fixed code example according to kriegaex comment.
Fixing the sample code
Before we start, there are two problems with your sample code:
1 * testMock(x) should be 1 * testMock.method(x)
callMethod should return double, not int, because otherwise the result would always be 0 (a double between 0 and 1 would always yield 0 when converted to an integer).
Please, next time make sure that your sample code not only compiles but also does the expected thing. Sample code is only helpful if it does not have extra bugs, which a person trying to help you needs to fix first before being able to focus on the actual problem later on.
The problem at hand
As you already noticed, interactions, even though lexically defined in a then: block, are transformed in such a way by Spock's compiler AST transformations, that they are registered on the mock when the mock is initialised. That is necessary because the mock must be ready before calling any methods in the when: block. Trying to directly use a result only known later while already executing the when: block, will cause the problem you described. What was first, chicken or egg? In this case, you cannot specify a method argument constraint, using the future result of another method calling the mock method in the constraint.
The workaround
A possible workaround is to stub the method and capture the argument in the closure calculating the stub result, e.g. >> { args -> arg = args[0]; return "stubbed" }. Of course, the return keyword is redundant in the last statement of a closure or method in Groovy. In your case, the method is even void, so you do not need to return anything at all in that case.
An example
I adapted your sample code, renaming classes, methods and variables to more clearly describe which is what and what is happening:
package de.scrum_master.stackoverflow.q72029050
import spock.lang.Specification
class InteractionOnCallResultTest extends Specification {
def "dependency method is called with the expected argument"() {
given:
def dependency = Mock(Dependency)
def randomNumber
def dependencyMethodArg
when:
randomNumber = new UnderTest().getRandomNumber(dependency)
then:
1 * dependency.dependencyMethod(_) >> { args -> dependencyMethodArg = args[0] }
dependencyMethodArg == randomNumber
}
}
interface Dependency {
void dependencyMethod(double x)
}
class UnderTest {
double getRandomNumber(Dependency dependency) {
double randomNumber = Math.random()
dependency.dependencyMethod(randomNumber)
return randomNumber
}
}
Try it in the Groovy Web Console.
I have a method, which inside calls a method which returns bool value - in this question let's name the method:
bool IsFilled(int value)
Now in another method which I am testing this is being called multiple times:
if (IsFilled(0))
{
if (IsFilled(1)){
...
} else {
...
}
}
for (int i = 1; i < range; i++)
{
if (IsFilled(i)) {
...
if (IsFilled(0)) {
}
}
}
Now how would one test it correctly with gtest? I am mainly going for coverage and testing branches more than values. As such I was expecting to do something like this:
EXPECT_CALL(adapter, IsFilled(0)).Times(zeroCalls).WillOnce(IndexZeroResults);
EXPECT_CALL(adapter, IsFilled(1)).Times(oneCalls).WillOnce(IndexOneResults);
EXPECT_CALL(adapter, IsFilled(_)).Times(otherCalls).WillOnce(IndexOtherResults);
I need the 0/1 calls separated as then I can test all branches, however, the "_" would duplicate the 0/1 calls as it tests with random values. Is it possible to exclude it?
TL;DR - swap the order of EXPECT_CALLs:
EXPECT_CALL(adapter, IsFilled(_)).Times(otherCalls).WillOnce(IndexOtherResults);
EXPECT_CALL(adapter, IsFilled(1)).Times(oneCalls).WillOnce(IndexOneResults);
EXPECT_CALL(adapter, IsFilled(0)).Times(zeroCalls).WillOnce(IndexZeroResults);
This works because of GoogleMock rules for ordering EXCEPT_CALLs. Expectations are always considered in reverse order than they were declared (so last declared expectation is verified first). It is like that to allow you to create general expectations in test fixture and specific expectations in test body.
I have a class who's only task is to take a List<Object> and return a sorted List<Object>. For an example the sort method in the class works with a procedure which places the Objects randomly in the list.
Trying to do: to write the test for that sorting method (or class) which must fail if the sorting is in fact just random. That means I need to find the List<Object> order to test I assume.
Code to be tested
class RootLoggerFirstSorter {
List<LoggerConfig> sort(List<LoggerConfig> unSortedList) {
List<LoggerConfig> levelSortedList = new ArrayList<>(unSortedList);
Collections.sort(levelSortedList, new Comparator<LoggerConfig>() {
#Override
public int compare(LoggerConfig o1, LoggerConfig o2) {
if (o1.getLevel().intLevel() == o2.getLevel().intLevel()) {
return 0;
} else if (o1.getLevel().intLevel() < o2.getLevel().intLevel()) {
return 1;
} else {
return -1;
}
}}
);
LinkedList<LoggerConfig> sortedList = new LinkedList<LoggerConfig>();
for(Iterator<LoggerConfig> i = levelSortedList.iterator(); i.hasNext();) {
LoggerConfig cfg = i.next();
addNextLoggerConfig(cfg, sortedList);
}
return sortedList;
}
private void addNextLoggerConfig(LoggerConfig cfg, LinkedList<LoggerConfig> sortedList) {
if(cfg.getName() == null || cfg.getName().isEmpty()) {
sortedList.addFirst(cfg);
} else {
sortedList.addLast(cfg);
}
}
}
Tried
.....
expect(item1.getLevel()).andStubReturn(Level.DEBUG);
expect(item2.getLevel()).andStubReturn(Level.ERROR);
expect(item3.getLevel()).andStubReturn(Level.INFO);
.....
//Ignore the pre req for test setup
#Test
public void testSort() {
List<LoggerConfig> unsortedList = makeUnsortedList();
EasyMock.replay(item1,item2,item3);
List<LoggerConfig> sortedList = tested.sort(unsortedList);
assertThat("First item on the list is ERROR level: ", sortedList.get(0).getLevel(), is(Level.ERROR) );
assertTrue(sortedList.get(1).getLevel().equals(Level.INFO) || sortedList.get(1).getLevel().equals(Level.INFO));
assertTrue(sortedList.get(2).getLevel().equals(Level.DEBUG) || sortedList.get(2).getLevel().equals(Level.DEBUG));
}
But this test will always pass since if looked at the index 1 and 2 only, index 0 will always contain the LoggerConfig with an empty name [set up is done that way]). So I thought Should I just unit test the compare method instead? If yes, how?
Problem The issue is that I need to test the sort method with a particular Object property which is the level of the LoggerConfig object. So the test must check the List order.
Many different aspects here:
Of course you do not need to test the built-in Collections.sort() method.
In that sense: instead, you want to test two aspects A) that you are actually calling that sort method B) that your comparator works as expected.
A) is achieved by the code you put in your own answer. Or to be precise: you only need one test case where you sort check for an expected result; after providing a specific test input to your method.
B) is achieved by writing test code that simply checks that compareTo() returns the expected result for the different input
In the end, this is about properly dissecting your logic into classes. Of course you can declare that comparator as anonymous inner class; and just verify that the sort method returns the expected result.
But when you make the comparator, say an inner class somewhere, you could write unit tests for just the comparator functionality.
Finally: your test case does not mean the goal that you stated: must fail if the sorting is in fact just random. You see, if the result of sort() is random, that it could randomly give you a correct result. Meaning: you can't expect a single test to verify "possibly random behavior". You would have to run many tests with a lot of different data, and verify that all of them pass; to achieve a certain confidence that the sort() isnt pure random.
But as said: you are not sorting. You are calling the built-in sort method which does not need to be tested.
I assumed the List<ConfigLogger> followed something like item1["", ERROR], item2["com.fwk.foo", DEBUG], item3["com.fwk.core.baa", INFO]. So in that case I needed to check that if item3 is in the position 1 and item2 is in position 3 in the list the implementation does the sort correctly. So test I needed was as follows:
#Test
public void testSort() {
List<LoggerConfig> unsortedList = makeUnsortedList();
EasyMock.replay(item1,item2,item3);
List<LoggerConfig> sortedList = tested.sort(unsortedList);
assertFalse(unsortedList.equals(sortedList));
assertTrue(sortedList.get(0).getName().isEmpty());
LoggerConfig cfg1 = sortedList.get(1);
LoggerConfig cfg2 = sortedList.get(2);
assertThat(cfg1.getLevel(), is(Level.DEBUG));
assertThat(cfg2.getLevel(), is(Level.INFO));
}
So I am accessing the item from the list and comparing if they are same as expected.
Should I just unit test the compare method instead?
No, you should not. The test may fail if you try to refactor the sort method later. You are actually trying to assert that the sorting is done probably. The compare method is just an implementation detail. You may not use the compare method to sort the list in the future.
Of course you also don't need to test the built-in sort method because you are actually testing your custom sort method. Anything inside this sort method is implementation details including the list.sort method you called. You should pretend that you don't know about it when you are writing a test.
Other than that, your sort method also contain some logic that is not related to the built-in sort method.
I am still trying to get the hang of unit testing, I have a simple question. Today I wanted to write a test for a very simple function. This function was doing just this:
void OnSomething()
{
increment++;
if (increment == 20)
SaveIt();
}
I said, this function could be testable. I could write a test that calls it 20 times and then verifies that SaveIt has been called.
Then my doubt arose. How can I test that SaveIt has been called? My first answer was to add a boolean, but then I thought: is it correct to add class features just to make it testable?
Please advise. Thank you.
I would suggest having SaveIt return a success or failure result, this just makes it easier to test overall. You could do something as simple as having it return a bool, or you could create a generic result class that contains the ability to set messages as well, if you ever need to report whether it passed or failed.
A simple example example
public class Result
{
public bool IsSuccess;
public List<string> Messages;
}
In the unit test you're trying to test only the OnSomething behavior though -- what happens inside "SaveIt" should not be tested. So ideally you'd want SaveIt() to occur in another class so you can mock its response.
I use Moq for this purpose. Moq is free, you can get it here: http://code.google.com/p/moq/
my method would then become
Result OnSomething()
{
Result result=null;
increment++;
if(increment == 20)
{
result = saver.SaveIt();
}
return result;
}
Your class constructor would take an object that implements ISaver interface (defining SaveIt() method) (ideally injected by a DI framework but you could generate it manually if you had to).
Now in your unit test you would create a mock version of ISaver and tell it what to return when it gets called:
Mock<ISaver> mock = new Mock<ISaver>();
mock.Setup(x=> x.SaveIt()).Returns(new Result{IsSuccess=true});
You'd instantiate your class passing mock.Object in the constructor ISaver parameter.
ex.
MyClass myClass = new MyClass(mock.Object);
//(assuming it didn't have other parameters)
Then, you could Assert whether result is null or not -- if it never got called, it would be null because the setup you did above would never trigger.
(in nunit)
Result result = myClass.OnSomething();
Assert.IsNotNull(result);
If you really didn't want OnSomething() to return a result, or it couldn't because it's an event, then I would have OnSomething() call a method to do the work for you:
void OnSomething()
{
Result result = DoTheWork();
}
Result DoTheWork()
{
Result result=null;
increment++;
if(increment == 20)
{
result = saver.SaveIt();
}
return result;
}
And then run your unit test on DoTheWork() instead of OnSomething().
Definitely not! Production code should not depend on tests at all, but the tests should verify the correct behaviour of the actual code. This can be achieved by several methods, such as IOC, and using mocks. You can take a look at some existing frameworks which simplify your life a lot:
http://code.google.com/p/mockito/
http://code.google.com/p/jmockit/
http://www.easymock.org/
so this is the class that i want to test. and specifically i just pick one of the function that i want to test. while var is a value returned from doing some function from classB bar is instance from classC and then do some function which pass some variables. for most of the hints/example, the function to be tested is return a value. so my question is, how to test that this particular function worked?
thanks.
class mA extends A {
...
function doSomething($foo) {
$var = doStuffFromClassB("hallo");
$bar = ClassC::instance();
$bar->doStuffFromClassC($var, $foo, "world");
}
}
If it's called doSomething and it doesn't indicate what it does by returning a value, then you can use mock objects to trace the interaction with the other objects.
See PhpUnit's documentation on mock objects. I guess in this case you want to verify that the doStuffFromClassC method is involved with the var from doStuffFromClassB.