In Google Mock, is there any inverse of InSequence? E.g. OutOfSequence
E.g. the assertion only works if the correct sequence does NOT occur.
AFAIK, there is not a feature like that which you can use directly, however, it's not hard to get to what you want.
Say you want the test fail if the following sequence of calls happen:
Disconnect() -> Connect()
You ask EXPECT_CALL to register the call sequences in a vector and then you can check to see if the sequence vector is what you expected. You can do this using Invoke, by using WillOnce and a lambda function that gets invoked when the function is called.
Here is an example that checks if Disconnect() -> Connect() sequence does not happen.
using ::testing::ElementsAre;
using ::testing::Not;
// Test if two functions are called out of sequence.
TEST(AtmMachine, OutOfSequence) {
std::vector<std::string> sequenceVector;
// Arrange
MockBankServer mock_bankserver;
// Assuming we want the test fail if Disconnect happens before Connect.
// We store their sequence in sequenceVector.
EXPECT_CALL(mock_bankserver, Disconnect())
.Times(1)
.WillOnce(
[&sequenceVector]() { sequenceVector.push_back("Disconnect"); });
EXPECT_CALL(mock_bankserver, Connect())
.Times(1)
.WillOnce([&sequenceVector]() { sequenceVector.push_back("Connect"); });
// Act
AtmMachine atm_machine(&mock_bankserver);
atm_machine.Withdraw(1234, 1000);
// Assert that the Disconnect() -> Connect() does not happen
EXPECT_THAT(sequenceVector, Not(ElementsAre("Disconnect", "Connect")));
}
Related
I want to mock requests with ktor's http client using MockK. The problem is all the methods related to making requests with the client are inline, so I cannot use coEvery on those methods. The next thing I tried was to go through the called methods until I found a method that wasn't inline and then mock that. After stepping through some functions, the HttpClient.request() function instantiates an HttpStatement and then calls execute() on it.
public suspend inline fun HttpClient.request(
builder: HttpRequestBuilder = HttpRequestBuilder()
): HttpResponse = HttpStatement(builder, this).execute()
If I can mock the constructor and .execute() functions, I can intercept the call and return my canned response. I can then check that the builder's params are correct inside of a verify function.
mockkConstructor(HttpStatement::class)
coEvery { anyConstructed<HttpStatement>().execute() } returns mockk {
coEvery { status } returns HttpStatusCode.OK
coEvery { body<RefreshToken>() } returns RefreshToken()
}
This code takes care of intercepting the execute call. The next step would be to verify the constructor params of HttpStatement. This code to verify execute was called works:
coVerify { anyConstructed<HttpStatement>().execute() }
Next thing is to verify the constructor params. This pull request in the MockK repo describes how to verify constructors:
coVerify { constructedWith<HttpStatement>(/* Matchers here */).execute() }
Note that I have to add the .execute() or else MockK tells me I'm not verifying anything.
Missing calls inside verify { ... } block.
io.mockk.MockKException: Missing calls inside verify { ... } block.
at app//io.mockk.impl.recording.states.VerifyingState.checkMissingCalls(VerifyingState.kt:52)
at app//io.mockk.impl.recording.states.VerifyingState.recordingDone(VerifyingState.kt:21)
...
Ok, so just add in the matchers. However, no combination of matchers I try works. I've tried doing a bunch of constant matchers for type Any (which should match anything right?)
coVerify { constructedWith<HttpStatement>(ConstantMatcher<Any>(true))}
I've tried a matcher for HttpRequestBuilder and HttpClient
coVerify {
constructedWith<HttpStatement>(
ConstantMatcher<HttpRequestBuilder>(true),
ConstantMatcher<HttpClient>(true)
).execute()
}
And a whole slew of others. Each time, I get this error:
Verification failed: call 1 of 1: HttpStatement(mockkConstructor<HttpStatement>(any(), any())).execute(any())) was not called
java.lang.AssertionError: Verification failed: call 1 of 1: HttpStatement(mockkConstructor<HttpStatement>(any(), any())).execute(any())) was not called
at io.mockk.impl.recording.states.VerifyingState.failIfNotPassed(VerifyingState.kt:63)
at io.mockk.impl.recording.states.VerifyingState.recordingDone(VerifyingState.kt:42)
...
Next thing I figured I could try would be to use an answers block earlier on in order to print out the types of the parameters being passed in case I was wrong, but that also runs into the "nothing being done in every block" error.
coEvery { anyConstructed<HttpStatement>() } answers {
args.filterNotNull().map { it::class.qualifiedName }.forEach(::println)
mockk {
coEvery { execute().status } returns HttpStatusCode.OK
coEvery { execute().body<RefreshToken>() } returns RefreshToken(
accessToken = accessToken,
expiresIn = expiresIn,
)
}
}
Is there a solution to mocking the http client? Do I have to mock something even more internal? Or do I just have to stick to using the ktor MockEngine?
I'm trying to call a JS-function from C++ using v8/Nan which in turn returns a Promise.
Assuming I have a generic Nan Callback
Nan::Callback fn
I then call this function using the following code
Nan::AsyncResource resource(Nan::New<v8::String>("myresource").ToLocalChecked());
Nan::MaybeLocal<v8::Value> value = resource.runInAsyncScope(Nan::GetCurrentContext()->Global(), fn, 0, 0);
The function is being called correctly, and I receive the promise on the C++ side
v8::Handle<v8::Promise> promiseReturnObject =
v8::Handle<v8::Promise>::Cast ( value.ToLocalChecked() );
I can then check the state of the promise using
v8::Promise::PromiseState promiseState = promiseReturnObject->State();
Of course at the time the promise is still pending, and I can't access it's result. The only way I've found so far to receive the result of that promise is by using the Then method on the promiseReturnObject.
promiseReturnObject->Then(Nan::GetCurrentContext(), callbackFn);
Is there any way to retreive that result synchronously in the scope of the function that calls fn? I've tried using std::promise and passing it to as a data argument to v8::FunctionTemplate of callbackFn, but calling wait or get on the respective std::future blocks the execution and the promise is never fulfilled. Do I need to resort to callbacks?
Any help or idea on how I could set this up would be much appreciated.
I derived an answer from https://github.com/nodejs/node/issues/5691
if (result->IsPromise()) {
Local<Promise> promise = result.As<Promise>();
if (promise->HasHandler()) {
while (promise->State() == Promise::kPending) {
Isolate::GetCurrent()->RunMicrotasks();
}
if (promise->State() == Promise::kRejected) {
Nan::ThrowError(promise->Result());
}
else
{
// ... procses promise->Result() ...
}
}
}
So I've got this simple MPI example thrown together. I'm seeing some weird behavior around testing boost::mpi::request that I can't explain. Specifically, if you remove the commenting on the second loop, it spins forever. Does test on a boost::mpi::request only return true once? If so, what bit of state is getting updated? I've poked through Boost's MPI and optional code and I can't explain what I'm seeing.
(naturally, for the uninitiated, you'll need to use mpiexec with two nodes to run this yourself.)
# include "stdafx.h"
# include <boost/serialization/string.hpp>
# include <boost/mpi.hpp>
# include <windows.h>
# include <iostream>
# include <boost/mpi.hpp>
# include <boost/optional.hpp>
int main(int argc, char *argv[]);
int main(int argc, char *argv[])
{
boost::mpi::environment m_env;
boost::mpi::communicator m_world;
if (m_world.rank() == 0)
{
m_world.send(1,0, std::string("hi!"));
}
else
{
std::shared_ptr<std::string> rcv = std::shared_ptr<std::string>(new std::string());
boost::mpi::request x = m_world.irecv(0, 0, *rcv);
while (!x.test())
{
Sleep(10);
}
//while (!x.test())
//{
// Sleep(10);
//}
std::cout << *rcv;
}
}
The answer is in the documentation, sort of:
/**
* Determine whether the communication associated with this request
* has completed successfully. If so, returns the #c status object
* describing the communication. Otherwise, returns an empty #c
* optional<> to indicate that the communication has not completed
* yet. Note that once #c test() returns a #c status object, the
* request has completed and #c wait() should not be called.
*/
optional<status> test();
Then look at the docs for the underlying MPI_Test function:
A call to MPI_TEST returns flag = true if the operation identified by request is complete. In such a case, the status object is set to contain information on the completed operation; if the communication object was created by a nonblocking send or receive, then it is deallocated and the request handle is set to MPI_REQUEST_NULL.
One is allowed to call MPI_TEST with a null or inactive request argument. In such a case the operation returns with flag = true and empty status.
So what we see is that Boost MPI's test() method returns an optional<status>, and MPI_Test() can only return a status once (after that, the request is destroyed). MPI_Test() called repeatedly would return flag = true, but that's not what you're checking. If you really need this pattern, you could probably call MPI_Test() yourself and use the returned flag instead of status. Or just do the bookkeeping in your application, and don't call boost::mpi::request::test() twice on the same request.
Another way to look at this problem is that you are using the result of test() in a boolean context, where you expect it to work like the flag of MPI_Test(), but actually it works like the status, and its bool nature is only an illusion.
This is consistent with the MPI standard. When MPI_TEST indicates the operation has completed, the returned status object will contain the information about the completed operation, and the operation object itself is marked inactive or de-allocated (whichever applies). Calling MPI_TEST again on that operation object would return an empty status.
The (latest version of the) MPI standard provides a way to access the status in a non-destructive way : MPI_REQUEST_GET_STATUS.
I'm not aware of an implementation of this operation in boost, but you can just store the returned status object, and refer to that later instead of calling test again.
I have mocked function like:
virtual void MyClass::foo(const std::function<void()>& callback);
I want to set expectation for foo:
EXPECT_CALL(MyClassMock, foo(testing::_));
and then I want to call received callback when expectation is fulfilled.
How to do that using gmock?
Option #1
EXPECT_CALL(MyClassMock, foo(testing::_))
.Times(1)
.WillOnce(testing::InvokeArgument<0>());
Option #2
EXPECT_CALL(MyClassMock, foo(testing::_))
.Times(1)
.WillOnce(testing::Invoke([](std::function<void()> f){f();}));
I have not tested this but the principle should get you there.
Change your EXPECT_CALL to repeatedly invoke a function. This function should be global/static, probably located in the same file as your expectations. Invoke automatically forwards the arguments so the parameter list should match.
EXPECT_CALL(MyClassMock, foo(testing::_))
.WillRepeatedly(Invoke(myCallbackFunc));
...
static void myCallbackFunc(const std::function<void()>& callback)
{
callback();
}
More ways of invoking functions after an EXPECT can be seen on the GoogleMock Cheat Sheet.
I'm using NSubstitute to mock a class that my method under test uses. This mocked class may throw a particular exception under certain conditions.
The method that I'm testing has some "retry" logic that it executes when it catches this exception. I'm trying to test this retry logic. So, I need a particular method of this mocked class to throw the exception sometimes, but not other times. Unfortunately, the method that throws this exception has no parameters, so I can't base the throw logic on parameters.
How can I make the mocked object's method throw the exception either:
A) ...the first N times it's called
or
B) ...based on the parameters some other method that's called before it
or
C) ...under any other condition other than the parameters passed in
To give you a clearer picture of what I'm trying to do, my code is something like:
IDataSender myDataSender = GetDataSender();
int ID = GetNextAvailableID();
myDataSender.ClearData();
myDataSender.Add(ID,"DataToSend");
bool sendSuccess = false;
while (!sendSuccess)
{
try
{
myDataSender.SendData();
sendSuccess = true;
}
catch (IDCollisionException)
{
ID++;
MyDataSender.ClearData();
myDataSender.Add(ID,"DataToSend");
}
}
So, I need to test my retry logic, and I need to simulate that IDCollisionException. However, I can't have the SendData() throwing the exception every single time, or the retry loop will never succeed.
What can I do here?
If I understand the question correctly, you can use When..Do and close over a local variable to get this behaviour.
const int throwUntil = 3;
var callsToSendData = 0;
var dataSender = Substitute.For<IDataSender>();
dataSender
.When(x => x.SendData())
.Do(x =>
{
callsToSendData++;
if (callsToSendData < throwUntil)
{
throw new DbCollisionException();
}
});
Similarly, you can also use callbacks to locally capture parameters passed to other methods, and access them within the Do block (rather than just using a counter).