Accessing test info in Google Test parameterized test case (`TEST_P`) - c++

When I create a regular TEST (or TEST_F), I can access to the test case information stored in test_info_, like:
TEST_F(MyTestSuite, TestCaseOne)
{
// ...
test_info_->name(); // will return "TestCaseOne"
}
I would like to access this kind of information when I use the parameterized (TEST_P) variant, which allows me to define fixture-based tests.
Looking under the hood, I can see that TEST_P works quite differently than her cousins TESTand TEST_F, as it registers the new test case by calling ::testing::UnitTest::GetInstance()->parameterized_test_registry().GetTestCasePatternHolder<test_case_name>(#test_case_name, __FILE__, __LINE__)->AddTestPattern(...) method. I understand that the class inheriting from TestWithParam will then run all the registered TEST_Ps test cases.
Is there a way to access (either runtime or compile time) to the name (string) of a TEST_P?

There's actually a getter for the TestInfo instance. From the documentation:
To obtain a TestInfo object for the currently running test, call
current_test_info() on the UnitTest singleton object:
// Gets information about the currently running test.
// Do NOT delete the returned object - it's managed by the UnitTest class.
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
printf("We are in test %s of test case %s.\n",
test_info->name(), test_info->test_case_name());

Related

Mocking a return value for a companion object method mockito

I'm having an issue with mocking a class with a companion object using mockito. It looks similar to this
#Component
class Util {
companion object {
fun generateName(job: Job) {
return job.name + "_" + (System.currentTimeMillis()/100L).toString()
}
}
}
I am trying to mock this class so I can do something like this:
I mocked the utility in test file like
var util : Util.Companion = mock()
Now inside my test I want to do the following:
#Test
fun "test function"() { //(dont have the symbols, not using the work laptop, excuse the syntax error)
whenever(util.generateName(job)).thenReturn("mystring")
}
Since our job names contain timestamps, I need this to work otherwise my unit tests won't work. Needless to say, this whenever is not working and my functions return the "correct" result when mocked, instead of the one I want provided in the return clause, otherwise during inserts I will always get nulls since I can't mock the timestamps. Please don't suggest different mocking libraries and such, there's already almost 100 tests written with mockito, so that is not an option.
You need to mock creating the companion object, which means compiler creates empty constructor of the class and use that constructor to create the companion object of that class.
You need specifically to return mocked object whenever the constructor is called, i.e new instance for that calls is created.
This doesn't play well with Mockito. I won't suggest you PowerMockito, that's like shooting yourself in the stomach.

What is exactly mocking in unit testing?

I am trying to test an http server functionality and this is the first time I get exposed to the notions of mocks, stubs and fakes. I'm reading this book that it says mocking is describing the state of a complex object at a certain moment, like a snapshot, and testing the object as it is actually the real one. right? I understand this. what I don't understand is what is the point of writing unit tests and assertions of certain cases that we fully describe in the mock object. If we set the expectations of arguments and return values on the mocking object, and we test for those exact values, the test will always pass. Please correct me. I know I am missing something here.
Mocks, Stubs or anything similar serves as a substitute for the actual implementation.
The idea of mocks is basically to test a piece of code in a isolated environment, substituting the dependencies for a fake implementation. For example, in Java, suppose we want to test the PersonService#save method:
class PersonService {
PersonDAO personDAO;
// Set when the person was created and then save to DB
public void save(Person person) {
person.setCreationDate(new Date());
personDAO.save(person);
}
}
A good aproach is creating a unit test like this:
class PersonServiceTest {
// Class under test
PersonService personService;
// Mock
PersonDAO personDAOMock;
// Mocking the dependencies of personService.
// In this case, we mock the PersonDAO. Doing this
// we don't need the DB to test the code.
// We assume that personDAO will give us an expected result
// for each test.
public void setup() {
personService.setPersonDao(personDAOMock)
}
// This test will guarantee that the creationDate is defined
public void saveShouldDefineTheCreationDate() {
// Given a person
Person person = new Person();
person.setCreationDate(null);
// When the save method is called
personService.save(person);
// Then the creation date should be present
assert person.getCreationDate() != null;
}
}
In another words, you should use mock to substitute dependencies of your code to an "actor" that can be configured to return an expected result or assert some behaviours.

OCMock and AVCaptureDeviceInput

I'm in the process of updating our test suite from OCMock 2 to OCMock 3 and am running into a few issues.
One of the issue is that we're trying to mock AVCaptureDeviceInput.
For one of the test we want to return a mocked instance AVCaptureDeviceInput when a class method is called on AVCaptureDeviceInput.
in our setup method:
self.mockAVCaptureDeviceInputClass = [OCMockObject mockForClass:[AVCaptureDeviceInput class]];
in our test:
id deviceInput = [OCMockObject mockForClass: [AVCaptureDeviceInput class]];
[[[[self.mockAVCaptureDeviceInputClass stub] classMethod] andReturn:deviceInput]
deviceInputWithDevice:mockDevice error:((NSError __autoreleasing **)[OCMArg setTo:nil])];
The issue seems to be that deviceInput overwrites the self.mockAVCaptureDeviceInputClass so that when the classMethod is stubbed, it does not do anything.
An alternative I tried to work around this was to create a mock for an instance of AVCaptureDeviceInput, but that just hangs:
[OCMockObject partialMockForObject: [AVCaptureDeviceInput new]];
with the following stack trace:
0x000000010938a219 in _object_set_associative_reference ()
0x0000000108aed5c3 in OCMSetAssociatedMockForClass at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCMFunctions.m:226
0x00000001144ecce2 in -[OCClassMockObject prepareClassForClassMethodMocking] at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCClassMockObject.m:89
0x00000001144ec934 in -[OCClassMockObject initWithClass:] at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCClassMockObject.m:31
0x00000001144f47f6 in -[OCPartialMockObject initWithObject:] at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCPartialMockObject.m:33
0x00000001144f1cdd in +[OCMockObject partialMockForObject:] at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCMockObject.m:58
0x00000001144e9abe in -[dfsaTests testExample] at /Users/otusweb/Desktop/dfsa/dfsaTests/dfsaTests.m:33
You are running into a common issue: only one mock object can mock class methods for a given class. This is is documented in the limitations section (http://ocmock.org/reference/#limitations). Currently the last mock created "wins".
What happens in your case is that you set up the first mock in your setup method (self.mockAVCaptureDeviceInputClass) but then you create a second mock for the same class in your test (deviceInput). At this point only the latter one can stub class methods on AVCaptureDeviceInput.
This problem is getting so common that I have decided to add a warning to OCMock. I'm thinking about the mock object printing a warning in cases where it has active stubs when it gets deactivated for class method stubbing. FWIW, there is some investigation under way to see whether it's possible to have more than one mock object mock class methods on the same class (https://github.com/erikdoe/ocmock/issues/173), but that's not trivial.

Unit testing code that uses a Singleton

I have code that uses a Singleton (this happens to be for a website, so the Singleton has the scope of just that one Request; each Request will have their own singleton).
My code (which happens to be in an HttpModule) does the following:
1 - Checks if the Singleton object is null and, if so, initializes it.
2 - Updates a property on this singleton object along the lines of:
if(A)
{
SingletonHolder.Current.X = Y;
}
else
{
SingletonHolder.Current.X = Z;
}
I then want to have some unit tests around this method to check that logic is correct. Let's say for argument's sake that we want the following 4 tests:
GivenMethodCall_WhenA_ThenXSetToY
GivenMethodCall_WhenA_ThenXNotSetToZ
GivenMethodCall_WhenNotA_ThenXSetToZ
GivenMethodCall_WhenNotA_ThenXNotSetToY
These tests all work perfectly when run one-at-a-time, but when run in VS2013 with the NUnit test runner then we get some failures because each test is run in parallel and the method under test is updating the same singleton object's property with different values.
Any advice on a pattern that would solve this?
Thanks
Griff
You probably just need to provide a method within your test fixture decorated with the SetUpAttribute method to perform initial setup before each test method is run and another method decorated with the TearDownAttribute that runs after each test method. The documentation for the nUnit SetUpAttribute is found here.
This will allow you to (in your SetUp method) initialize your Singleton object, and then (in your TearDown method) to set your Singleton object to null so that SetUp can re-instantiate/initialize the object for the next test.

Unexpected behaviour of XCTestCase -- create different instance to run test methods

I write unit test case with XCTestCase, and initialize variables in -setUp as following:
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_myPath = #"Path";
});
}
But when I try to use myPath in test cases, it only works in the first one, and the "myPath" would be in nil in subsequent cases.
So I set break point in -setUp to see what's happen. And I found that it create new instances for each methods!!
To double check it, I create a new project and test target to log testcase address as following:
#implementation fooTestTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
NSLog(#"<fooTestTests: %p>", self);
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(#"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
- (void)testExample2
{
XCTFail(#"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
#end
And the result is :
fooTest[846:303] <fooTestTests: 0x1005ab750>
fooTest[846:303] <fooTestTests: 0x1005ab7f0>
Since the XCTestCase was designed as a object have one or more test method, it should not create different instance for each method.
In such situation, I don't know where to setup my test environment. Even though write setup code in -init, it still create new instance and call -init many times. Currently, I have only a few unit test, but when the number of tests grows, and the setup procedure becomes more complex, it would be a problem. Could anyone give me a suggestion?
Add Question Summary:
If I have 2 test methods in one testcase class, the behaviour would be:
Instantiate new testcase as object 1
-setUp
test 1
-tearDown
Instanitate new testcase as object 2
-setUp
test 2
-tearDown
Why it needs step 5?
The Answer
The answer provided by Jon Reid
More information:
Testcase class at XUnit Patterns
Apple docs - Testing with Xcode - Flow of Test Execution
To run a single test, this is the regular pattern of xUnit test frameworks, including XCTest:
Instantiate new test object
Invoke -setUp
Invoke test method
Invoke -tearDown
That concludes a single test. The test object itself will be destroyed at some later time outside of our control.
So don't use -init or -dealloc with test objects. Instead use -setUp and -tearDown which are guaranteed to be called before, and after, each test. But each test does operate on a brand-new instance of the object. This helps keep tests isolated.
So get rid of your dispatch_once.