///Here is my class
class State {
var state: Int = 10
}
open class Car {
var state:State = State()
fun changState(data: Int = 1) {
setState(data)
}
fun setState(data: Int = 0) {
state.state = data
}
}
/// Here is my Test
#Test
fun `test 1`() {
var mockCar = mockk<Car>()
every { mockCar.changState(any()) } just runs
every { mockCar.setState(any()) } just runs
mockCar.changState(10)
verify(exactly = 1) { mockCar.changState(any()) }
verify { mockCar.setState(any()) }
}
But it fails with this error
################################
java.lang.AssertionError: Verification failed: call 1 of 1: Car(#1).setState(any())) was not called.
Calls to same mock:
Car(#1).changState(10)
############################
You need to remove verify { mockCar.setState(any()) } - there is no way that this will ever be called, because you mocked
every { mockCar.changState(any()) } just runs
This means the stubbed method will do nothing, it just runs, so to speak.
I don't recommend writing tests that only test mocks, because it will lead to a bias that the code is fine when you just use outputs of what you think is correct behavior. Instead, write a separate unit test for Car.
For your use-case a mock is not the intended thing to use, you should be using a spy instead if you mix real method calls with mocked behavior.
Related
I'm trying to write some unit tests for the following Kotlin code which uses async to create coroutines:
class ClassToTest(val dependency1: Dependency1, val dependency2: Dependency2) {
fun funToTest(list: List<X>) {
runBlocking {
val deferreds: List<Deferred<Type>> = list.map { item ->
async(Dispatchers.Default) {
val v1 = dependency1.func1(item)
val v2 = dependency2.func2(v1)
someFunc(v2)
}
}
val results = deferreds.awaitAll()
}
}
}
I mocked both dependency1 and dependency2 in the unit testing and provided a list of 2 items as input to the funToTest. I also mocked how the dependencies should return values based on different input, something like below
val slot1 = slot<>()
every {dependency1.func1(capture(slot1))} answers {
if (slot1.captured.field == xxx) {
return1
} else {
return2
}
}
//similar thing for dependency1
// invoke funToTest
However this doesn't seem like working as I'm getting unexpected results which indicated the mocked object didn't return results as desired between two coroutines.
Does anyone have any ideas what went wrong with these code?
I am trying to validate that a suspend function does not return anything at all in a certain test.
Consider the following situation:
val completionSignal = Channel<Unit>(capacity = 1, onBufferOverflow = BufferOverflow.DROP_LATEST)
suspend fun waitForCompletionSignal(): String {
completionSignal.receive()
return "Completion signal received"
}
I want to test this code with 2 unit tests, one that validates it returns the string when I provide the CompletionSignal with a value (thats the easy one).
And one that validates that it does not return anything when i don't give it anything. This is the hard one, since how long should I wait? And can i be sure the test fails if my code changes and suddenly the string is returned?
I got the following approach but I am missing some pieces:
#Test
fun `waitForCompletionSignal when completionSignal is provided assert result`() = runTest {
// Start waiting for result
val result = async { waitForCompletionSignal() }
// Provide completion signal
completionSignal.trySend(Unit)
// Await result and verify its correct
assertThat(result.await() == "Completion signal received")
}
#Test
fun `waitForCompletionSignal when completionSignal is not provided assert no result`() = runTest {
// Start waiting for result
val result = async { waitForCompletionSignal() }
// TODO?? some validation that succeeds if the test is just like this, but fails when i do the following:
completionSignal.trySend(Unit)
// A regular await would wait indefinately, and checking if the deferred result is completed does not work very well as well.
}
I hope the question is clear, thanks in advance.
I made an extension function on the deferred type to be able to wait for a max amount of time and after that it will return null. In my particular situation a delay time of 0 (so no delay whatsoever) is enough, but I can imagine that in some situations its useful to delay for a minimum amount of time.
#ExperimentalCoroutinesApi
suspend inline fun <reified T> Deferred<T>.awaitOrNull(
time: Long = 0,
crossinline actBlock: () -> Unit = { }
): T? = coroutineScope {
actBlock()
val timeoutJob = async<T?> {
delay(time)
null
}
return#coroutineScope select<T?> {
this#awaitOrNull.onAwait {
timeoutJob.cancel()
it
}
timeoutJob.onAwait {
this#awaitOrNull.cancel()
it
}
}
}
Using this method i can write the following tests that fail / succeed as expected:
// Succeeds
#Test
fun `waitForCompletionSignal when completionSignal is provided assert result`() = runTest {
val result = async {
waitForCompletionSignal()
}.awaitOrNull {
completionSignal.trySend(Unit)
}
assertThat(result == "Completion signal received")
}
// Succeeds
#Test
fun `waitForCompletionSignal when completionSignal is not provided assert no result`() = runTest {
val result = async {
waitForCompletionSignal()
}.awaitOrNull()
assertThat(result == null)
}
// Fails (to prove that it works)
#Test
fun `waitForCompletionSignal when completionSignal is not provided assert no result`() = runTest {
val result = async {
waitForCompletionSignal()
}.awaitOrNull {
completionSignal.trySend(Unit) // This (obviously) causes the test to fail, as I wanted.
}
assertThat(result == null)
}
Given the following setup:
class MockingFilters {
def filters = {
all(controller:"simple", action:"list") {
before = {
log.info "This needs asserting"
return false
}
}
}
}
Is there a way to assert that the log.info has fired? I am unsure how to get a handle on the Filter, and thus be able to interaction test the log object.
void "test list action is filtered"() {
when:
withFilters(action:"list") {
// Important bit
// Not sure how to get a handle to the filter
1 * log.info("This needs asserting")
controller.list()
}
then:
// Whatever here
}
There are also other objects on the Filter that I would like to test, but this example should be reflective of those too.
I am using shiro security in my grail application.
Grails version : 2.2.1
shiro : 1.2.0
I have a problem in writing grails unit test case for the controller with filter enabled. When the test case run without filters then it is working fine, if it runs withFilters then it is failing for accessControl() method not found in the controller. I dont know how to make Shiro's api to be visible while running the test case.I referred shiro unit test case link http://shiro.apache.org/testing.html but I couldn't get any info regarding accessControl().I have given sample code how my classes and test case looks like
MyController.groovy
def create() {
// getting request parameters and validation
String emailId = params.emailId
def ret = myService.createUser(emailId)
return ret
}
MyControllerFilters.groovy
def filters = {
loginCheck(controller: 'user') {
before = {
//do some business checks
// Access control by convention.
accessControl() // This is a dynamic method injected by ShiroGrailsPlugin to FilterConfig, but this is not visible during the test case.
}
}
MyControllerTests.groovy
#TestFor(MyController)
#Mock(MyControllerFilters)
class MyControllerTests {
#Before
void setup() {
// initializing some variables
}
void testCreateUserWithFilter() {
request.accessAllowed = true
withFilters(action:"create") {
controller.create()
}
assert response.message == "success"
}
}
Try to use:
ControllerOrService.metaClass.method = {
return "" //what you need to be returned
}
Add parameters to closure if method take parameters:
ControllerOrService.metaClass.method = { def a, def b ->
return a + b
}
Don't forget to use full name of method when you mock them in that way.
Consider the following, where I am testing that an injected dependency's method is called a specific number of times:
[Fact]
public void WhenBossTalksEmployeeBlinksTwice()
{
// arrange
var employee = new Mock<IEmployee>();
employee.Setup(e => e.Blink());
var boss = new Boss(employee.Object);
// act
boss.Talk();
// assert
employee.Verify(e => e.Blink(), Times.Exactly(2)); // Passes as expected
employee.Verify(e => e.Blink(), Times.Exactly(1)); // Fails as expected
}
When I force the failing test, the output is:
Moq.MockException: Invocation was not performed on the mock 1 times: e
=> e.Blink()
What would be better is something like:
Moq.MockException: Invocation was unexpectedly performed 2 times, not 1 time: e
=> e.Blink()
Here are the items involved with the test:
public interface IEmployee { void Blink(); }
public class Boss {
private readonly IEmployee _employee;
public Boss(IEmployee employee) { _employee = employee; }
public void Talk() {
_employee.Blink();
_employee.Blink();
}
}
Is it possible to harvest and display the actual number of times the dependency's method was called, in the failing test's error message?
I'm not sure that it matters, but I'm using Moq v3.1.416.3 (not the latest, I know, but another library I'm using hasn't updated to Moq 4.x yet…)
I don't know of a straight way to harvest the information in Moq3.
What I would do is use a callback on the setup of Blink.
int count = 0;
employee.Setup(e => e.Blink()).Callback(() => count++);
...
employee.Verify(e => e.Blink(), Times.Exactly(1), "Moq.MockException: Invocation was unexpectedly performed " + count + " times, not 1 time: e => e.Blink()"); // Fails as expected