Testing network which uses AFNetworking with OCMock - unit-testing

I have a class Network that contain next method:
- (void)fetchRecords {
Network * __weak weakSelf = self;
[self.sessionManager POST:#"" parameters:#{#"parameter":"param1"}
success:^(NSURLSessionDataTask *task, id responseObject) {
[weakSelf setRecordsWithLists:responseObject];
}
failure:nil];
}
Property sessionManager is AFHTTPSessionManager class.
I want to test my network communication. I want to check that if success block executed then invoked setRecordsWithLists: method.
I use OCMock, I googled and write next test code:
- (void)tesNetworkSuccessExecuteSetRecords {
id partiallyMockedSessionManager = [OCMockObject partialMockForObject:self.network.sessionManager];
[[partiallyMockedSessionManager expect] POST:OCMOCK_ANY parameters:OCMOCK_ANY success:OCMOCK_ANY failure:OCMOCK_ANY];
[[[partiallyMockedSessionManager expect] andDo:^(NSInvocation *invocation) {
void (^successBlock)(NSURLSessionDataTask *task, id responseObject);
[invocation getArgument:&successBlock atIndex:4];
successBlock(nil, #[#"first", #"second"]);
}] POST:OCMOCK_ANY parameters:OCMOCK_ANY success:OCMOCK_ANY failure:OCMOCK_ANY];
self.network.sessionManager = partiallyMockedAuthorizationSessionManager;
[self.network fetchRecords];
}
Please, tell how to return my own response for success block, if do it wrong. And how to verify that setRecordsWithLists: called from success block.

Well, you are actually setting the expectation twice, which would mean you are expecting the method to be called twice too. If that is not what you intend, you should delete the first expectation.
On the other hand, since you need to check if your method is called, you probably want to create a partial mock for your self.network object. With the partial mock (or spy), you can set the expectation for your method, with any argument you prefer, and verify it to complete the test.
Your code finally should look like this:
- (void)tesNetworkSuccessExecuteSetRecords {
id partiallyMockedSessionManager = [OCMockObject partialMockForObject:self.network.sessionManager];
[[[partiallyMockedSessionManager expect] andDo:^(NSInvocation *invocation) {
void (^successBlock)(NSURLSessionDataTask *task, id responseObject);
[invocation getArgument:&successBlock atIndex:4];
successBlock(nil, #[#"first", #"second"]);
}] POST:OCMOCK_ANY parameters:OCMOCK_ANY success:OCMOCK_ANY failure:OCMOCK_ANY];
id spyNetwork = OCMPartialMock(self.network);
[[spy expect] setRecordsWithLists:OCMOCK_ANY];
self.network.sessionManager = partiallyMockedAuthorizationSessionManager;
[self.network fetchRecords];
[spyNetwork verify];
}
Again, you may add the argument of your preference in the expectation. Beware of the name of the method, it should begin with 'test', otherwise it may not be run or recognized as a test by XCode.

Related

Truffle test doesn't seem to finish before "succeeding", and doesn't wait for transactionHash of a sent tx

Quick problem I've been slamming my head against since last night,
My truffle (v5.2.3) test file performs two (2) tests, that serially call() then actually send a transaction to make persistent changes on my smart contract's storage. These tests are as follow (sorry for the dumped file, I've minimized as much as I could):
const PassportManager = artifacts.require("PassportManager");
contract("PassportManager", accounts => {
it("should initialize a new passport linked with the current user's address", () => {
let this_address = accounts[0];
let this_nickname = "John Doe";
let meta;
return PassportManager.deployed()
.then(instance => {
meta = instance;
console.log("Test1 on PassportManager address: " + meta.address);
return meta.initPassport.call(this_nickname);
})
.then(returned_tuple => {
assert.equal(returned_tuple[0], this_nickname, "Nickname, passed and returned by PassportManager.initPassport(), should match!");
assert.equal(returned_tuple[1], this_address, "Controller address, passed and returned by PassportManager.initPassport(), should match!");
//If we're here, it means the previous call() has succeeded. Now,
//let's take things up a notch and let's actually send a transaction that changes the state of the blockchain.
//Remember: We can't check for return values with a transaction, we have to debug the tx id manually.
//#NOTE: We passed an extra parameter here. For more info on this special parameter object, check out:
//https://www.trufflesuite.com/docs/truffle/getting-started/interacting-with-your-contracts#making-a-transaction
const result = meta.initPassport.sendTransaction(this_nickname, {from: accounts[0]});
result.on('transactionHash', (hash) => {
console.log('TxHash', hash);
});
});
});
it("should add an identity file sha256 hash to a controlled passport", () => {
let this_address = accounts[0];
let doc_hash = "0x21f3a9de43f07d855f49b946a10c30df432e8af95311435f77daf894216dcd41";
let meta;
return PassportManager.deployed()
.then(instance => {
meta = instance;
console.log("Test2 on PassportManager address: " + meta.address);
return meta.addIDFileToPassport.call(this_address, doc_hash);
})
.then(returned_tuple => {
assert.equal(returned_tuple[0], this_address, "Passport controller, passed and returned by PassportManager.addIDFileToPassport(), should match!");
assert.equal(returned_tuple[1], doc_hash, "Document hash (bytes32), passed and returned by PassportManager.addIDFileToPassport(), should match!");
assert.equal(returned_tuple[2], 1, "Trust score of newly added doc_hash should be 1!");
//Now let's actually pass a concrete, actuallly persistent transaction instead of a call.
const result = meta.addIDFileToPassport.sendTransaction(this_address, doc_hash, {from: accounts[0]});
result.on('transactionHash', (hash) => {
console.log('TxHash', hash);
});
console.log("what the hell");
});
});
/*it("return false", () => {
assert(0==1);
});
*/
});
The first test calls, then sends a transaction just fine! At every truffle test that I run, I get nice, expected log results in my console:
Test1 on PassportManager address: 0x871bbABdAeA0721FEB5529A07119edC7f05aB508
✓ should initialize a new passport linked with the current user's address (71ms)
TxHash 0x0760cb2738da2a21cc404e0627e1008599fe81f2c3a6914a1b06ff712dc8adca
and now it continues to the 2nd test, where for some reason it doesn't send the transaction, even though the call succeeds!
Test2 on PassportManager address: 0x871bbABdAeA0721FEB5529A07119edC7f05aB508
what the hell
✓ should add an identity file sha256 hash to a controlled passport (58ms)
The assertions are succeeding, the returned results from my contract call are logged, we even reach the frustrated little what the hell which is BELOW the sendTransaction, but I never get a TxHash like on the sent transaction of the 1st it() test!
What is even weirder is that if I add a 3rd it() test, it works as expected:
Uncomment the it("return false", () => { assert(0==1); }); from my test block, and lo and behold:
Test2 on PassportManager address: 0x87465190eCBa7C287143f07653462a87464b1AbA
what the hell
✓ should add an identity file sha256 hash to a controlled passport (119ms)
1) return false
TxHash 0x9226311347487d294b0bcf5bc1f535636fe886f08dfa327f15de43318aad37d7
Events emitted during test:
---------------------------
/* I even get proper emitted event data from my contract! */
---------------------------
I've been losing hair on this since yesterday, and I smell some sort of concurrency/timing problem. Is there any way to control the sequence of sent transactions, or wait for one to be submitted and mined before moving on with the tests?
The weird sequence of printed console.log()s (for example, the third test failing before test 2 actually prints out the txHash and event data) is maybe pointing towards something like that, but I thought the result.on() block would ensure we're waiting for the tx to be mined!

Spock interaction verification ignoring call to Mock method

The following Spock test is failing to not counting the call to the Mock method:
def setup() {
mojo = new PactCreateVersionTagMojo()
mojo.pactBrokerUrl = 'http://broker:1234'
mojo.pacticipant = 'test'
mojo.pacticipantVersion = '1234'
mojo.tag = 'testTag'
}
def 'calls pact broker client with mandatory arguments'() {
given:
mojo.brokerClient = Mock(PactBrokerClient)
when:
mojo.execute()
then:
notThrown(MojoExecutionException)
1 * mojo.brokerClient.createVersionTag(
'test', '1234', 'testTag')
}
You can find it here.
The SUT code, removing the argument validation code, is:
class PactCreateVersionTagMojo : PactBaseMojo() {
override fun execute() {
...
createVersionTag()
}
private fun createVersionTag() =
brokerClient!!.createVersionTag(pacticipant!!, pacticipantVersion.orEmpty(), tag.orEmpty())
You can find it here.
The error is as follows:
I have a very similar example on the same project that passes just fine:
def 'passes optional parameters to the pact broker client'() {
given:
mojo.latest = 'true'
mojo.to = 'prod'
mojo.brokerClient = Mock(PactBrokerClient)
when:
mojo.execute()
then:
notThrown(MojoExecutionException)
1 * mojo.brokerClient.canIDeploy('test', '1234',
new Latest.UseLatest(true), 'prod') >> new CanIDeployResult(true, '', '')
}
override fun execute() {
...
val result = brokerClient!!.canIDeploy(pacticipant!!, pacticipantVersion.orEmpty(), latest, to)
}
You can find the test above here and the SUT here.
I have investigated the call that happens during the test, and it seems as expected.
Additionally, I try to create the verification with wildcard argument constraints, but it still didn't work.
It seems to me that I have misconfigured my test, but I can't spot the difference between the test that passes and my failing test.
Your fun createVersionTag(..) looks like this:
fun createVersionTag(
pacticipant: String,
pacticipantVersion: String,
tag: String) {
}
I do not speak Kotlin, but I think you ought to open the method because otherwise it is final, which means it cannot be overridden by a subclass and thus not be mocked or stubbed by conventional means. This is also the difference to open fun canIDeploy(..).

Mockito, how to verify parameters of ther method in the last time it was called

During executing unit test the method is called 3 times. Each time it's called with different parameters. I want to verify, that on the last time method was called with corresponding paramets.
Please, help me.
My method :
private void doHandle(Updategram updategram)
throws FixtureNotFoundException, DatatypeConfigurationException {
BetSyncObject betSyncObject = transformer.transformer(updategram);
EventTreeCreation event = betSyncObject.eventTree;
if (!event.getEvent().isEmpty()) {
Event event2 = event.getEvent().get(0);
long timestamp =
updategram.getHeader().getTimeStampUtc().toGregorianCalendar().getTimeInMillis();
String sportName = event2.getSportcode();
String id = event2.getExtId();
publisher.publishEvent(PROVIDER_NAME, betSyncObject, sportName, id, timestamp);
} else {
LOGGER.info("Empty event tree : {}", betSyncObject);
}
}
Test:
#Test
public void testCountAndSetResultLine() throws Exception{
EventPublisher eventPublisher = Mockito.mock(EventPublisher.class);
BetgeniusService betgeniusService = new BetgeniusService();
BetSyncObject expectedBetSyncObj = transformer.transformer(updategram);
ExecutorService service = Executors.newFixedThreadPool(3);
handle(betgeniusService, updategramFixture, service);
Thread.sleep(50);
handle(betgeniusService, updategramMarketSet, service);
Thread.sleep(50);
handle(betgeniusService, updategramResult, service);
service.shutdown();
service.awaitTermination(20000, TimeUnit.MILLISECONDS);
betgeniusService.getExecutor().shutdown();
betgeniusService.getExecutor().awaitTermination(20000, TimeUnit.MILLISECONDS);
Mockito.verify(eventPublisher, Mockito.times(3)).publishEvent(Mockito.anyString(), Mockito.any(BetSyncObject.class),
Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());
}
For this moment I am getting exception, because the publishEvent method is not called 3 times with exactly expectedBetSyncObj. It should be called with it only last time.
So, please tell how could I check that the publishEvent method was called with the expectedBetSyncObj object the last time.
I think you can achieve this with an ArgumentCaptor.
Use the ArgumentCaptor to get the arguments for all calls made and then later verify each one of them.
In your case you would verify that on the third call the argument (.get(2)) is the expected object.
So something like
ArgumentCaptor<BetSyncObject> betSyncObjectCaptor = ArgumentCaptor.forClass(BetSyncObject.class);
Mockito.verify(eventPublisher, Mockito.times(3)).publishEvent(Mockito.anyString(), betSyncObjectCaptor.capture(), Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());
List<BetSyncObject> capturedBetSyncObject = betSyncObjectCaptor.getAllValues();
assertEquals(expectedBetSyncObj, capturedBetSyncObject.get(2));

PHPUnit is reporting errors instead of recognizing assertFalse()

I am attempting to test a simple Laravel model which has required "password" and "email" properties. My test reads as follows…
public function testEmailIsRequired() {
$user = new User;
$user->password = 'derp';
// should not save
$this->assertFalse($user->save());
}
Rather than correctly agree that "this doesn't work" and a successful test, I’m getting…
1) UserTest::testEmailIsRequired
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation:
19 NOT NULL constraint failed: users.email
(SQL: insert into "users" ("password", "updated_at", "created_at")
values (derp, 2014-09-26 15:27:07, 2014-09-26 15:27:07))
[...]
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
I’m afraid that I’m a total novice here. It seems to me that PHPUnit ought to be suppressing the database driver’s own error reporting and just accepting "false"… help?
Your test is looking for the function to return false. Any other errors generated in your function will still be returned, since you are calling the function.
public function testEmailIsRequired()
{
$user = new User;
$user->password = 'derp';
// should not save
$this->assertFalse($user->save());
}
public function testMockSaveWorks()
{
$Mock = $this->getMock('User', array('save'));
// Set up the expectation for the getResult() method
$Mock->expects($this->any())
->method('save')
->will($this->returnValue(true));
$this->assertTrue($Mock->save());
}
class User()
{
...
public function save()
{
if( is_null($this->email) )
return false;
...
return true;
}
}
You should then use Mocks to remove the actual save() function and its tie in to your database, and have the mock return true to pretend to save the record to show that you have tested the module.

Unit Test Example for Test Driven Development- Should the Assert be AreEqual?

In the below example of a unit test, the test is attempting to validate the note is created. Shouldn't the Assert be an "Assert.AreEqual" to verify if the id's match?
[TestMethod()]
public void CreateNoteTest_Pass()
{
HomeController target = new HomeController(); // TODO: Initialize to an appropriate value
var note = new NotePM();
note.Text = "This is my test note" + DateTime.Now;
int id = note.NoteId;
note.CreatedByUserName = Membership.GetUser("danielle").UserName;
ActionResult actual;
actual = target.Create(note);
Assert.AreNotEqual(id, note.NoteId);
Assert.IsInstanceOfType(actual, typeof(RedirectToRouteResult));
I'm curious to know what the
target.create(note)
method does. It looks like it takes a NotePM instance and does some work on it (create it in the DB and get the ID, for example).
My guess is that this test is verifying that target.create actually altered note.ID. So it saves the value of note.ID in the variable id, then calls create(note) and asserts that the value of the ID actually changed to some new value.
Do you want to compare note and actual and verify that they are equal ?
If so, use AreEqual...
Ex:
Assert.AreEqual(note, actual, "Note's are not equal.");