NUnit delayed constraint does not appear to work in Unity3d - unit-testing

I'm attempting to check that a condition is met after n seconds. I thought I could use the After method to do this, but it's not working as I expected. Am I doing something wrong here?
The test seems to fail instantly, instead of after delayInMilliseconds.
Using Unity 2019.1.14f1, NUnit 3.5.0.0.
Example:
// fails
[Test]
public void TimePassed_Polling()
{
Assert.That(
() => Time.time > 5.0f,
Is.True.After(delayInMilliseconds: 6000, pollingInterval: 100));
}
// passes
[UnityTest]
public IEnumerator TimePassed_Wait()
{
yield return new WaitForSeconds(6.0f);
Assert.That(() => Time.time > 5.0f);
}

Related

Mockk AssertionError: Verification failed: call 1 of 1

///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.

Flutter/Dart unit testing, how to advance time for Timer

I have a Stream<T> in my flutter app which uses timeout() under hood. Everything works fine, but running unit tests takes a while, since they have to wait every time for the timeout.
As I can see from sources timeout() implementation is based on Timer(). Is there any way to artificially advance time for Timer() on unit test environment?
For example in RxJava there is TestScheduler which has methods like advanceTimeBy/advanceTimeTo. I am looking for similar functionality.
Update:
The code could look like this:
extension StreamEx<T> on Stream<T> {
/// timeout only the first emission
Stream<T> timeoutFirst(Duration timeLimit) =>
MergeStream([
take(1).timeout(timeLimit),
skip(1),
]);
}
My requirement for the test here is that its runtime should not depend on whatever passed as timeLimit to the method. It possible with RxJava but how to fix it at Darts streams.
Update:
The test could look like this:
void main() async {
group(
'StreamEx.timeoutFirst',
() {
const TIMEOUT = Duration(milliseconds: 100);
const DELAY = Duration(milliseconds: 110);
test(
'should throw `TimeoutException` if it took too long for the first emission',
() async {
final subject = BehaviorSubject<int>();
final stream = subject.timeoutFirst(TIMEOUT).dump('tag0');
expectLater(
stream,
emitsInOrder([
emitsError(isInstanceOf<TimeoutException>()),
emits(equals(1)),
emits(equals(2)),
]),
);
await Future.delayed(DELAY);
subject.add(1);
subject.add(2);
subject.close();
},
);
},
);
}

How to test resubscriptions to RxJS Observable with TestScheduler?

I have an observable which might throw an error. When it throws, I want to resubscribe to that observable and try again. For example with the retry() operator.
To test this retry-logic I would need to create a test-observable which will throw an error the first 2 times it's subscribed to, and only on 3rd time would produce a value.
I tried the following:
import { Observable } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { retry } from 'rxjs/operators';
// Setup for TestScheduler
function basicTestScheduler() {
return new TestScheduler((actual, expected) => {
expect(actual).toEqual(expected);
});
}
// The function we're going to test
function retryMultipleTimes(observable$) {
return observable$.pipe(retry(2));
}
describe('retryMultipleTimes()', () => {
it('retries twice when observable throws an error', () => {
basicTestScheduler().run(({ hot, cold, expectObservable }) => {
const observable$ = hot('--#--#--Y');
const expected = ' --------Y'; // This is what I want to get
const unexpected = ' --# '; // This is what I get instead
expectObservable(retryMultipleTimes(observable$)).toBe(expected);
});
});
});
Seems that with a hot() observable it always resubscribes to the same frame that produced the error, resulting in immediately throwing again.
I also tried with cold() observable, in which case I get ------# - that is, at each retry the observable starts again from the beginning, resulting in --#, --#, --# - never reaching --Y.
It seems that there isn't a way to do such a thing with RxJS TestScheduler. Or perhaps there is?
If the hot() and cold() observable-creators aren't up to the task, perhaps I can create my own... but how?
I also tried adding a little delay between retries, so I wouldn't resubscribe immediately to the current frame by implementing the retry-logic using retryWhen:
function retryMultipleTimes(observable$) {
return observable$.pipe(
retryWhen(errors => errors.pipe(
delayWhen(() => timer(2)), // wait 2 frames before each retry
take(2), // do maximum of 2 retries
concat(throwError('error')), // finish with error when no success after 2 retries
)),
);
}
But this didn't work either. Looks like the resubscription still happens to the same frame as before.
How could I make this test pass?
Figured out a solution for this. I can use iif() to create an observable which chooses at subscription time between two observables:
describe('retryMultipleTimes()', () => {
it('retries twice when observable throws an error', () => {
basicTestScheduler().run(({ cold, expectObservable }) => {
let count = 0;
const observable$ = iif(
() => ++count <= 2,
cold('--#'),
cold('--Y'),
);
// --#
// --#
// --Y
expectObservable(retryMultipleTimes(observable$)).toBe('------Y');
});
});
});

Add optional message parameter to assertEquals

Disclaimer: I'm totally new to Haxe, but I have experience in many other languages.
I have tests similar to the following:
function doTest(type:SomethingMagic, tests:Array<Array<Int>>) {
for (t in tests) {
var res = DoSomeMagicalWork(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]);
assertEquals(type, res.type);
}
}
The problem with this is that the unit test framework, when run on many different arrays, doesn't give me the correct line for which the test failed. In other words, if I'm running this method with a bunch of arrays, like:
doTest(SOME_MAGIC_TYPE,
[[0, 0, 0, 1625, 0, 35, 0, 0, 0, 0, 0],
...
]);
and one of these lines fails, it doesn't tell me which line failed. Now, I know that I could probably restructure these tests to be a bit more intuitive anyway, but this was written by someone else, and I don't have the ability to change each of these at the moment.
What I'd like to do is the following:
function doTest(type:SomethingMagic, tests:Array<Array<Int>>) {
var number = 0;
for (t in tests) {
var res = DoSomeMagicalWork(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]);
assertEquals(type, res.type, "Test #" + number + " for type " + type);
number++;
}
}
So, basically, I'd like to be able to pass in some extra messaging information to the assertEquals function, similar to what one can do in other unit testing frameworks. Then, upon failure, it would output the standard assertion message, possibly appended by the additional message I sent as a parameter to the function. Originally, I thought it was as simple as sub-classing haxe.TestCase, but that doesn't appear to be quite as simple as I thought, due to the way Haxe interprets types (apparently).
Has anyone had success with something similar to this that could give me a recommendation on how to accomplish it?
If you want to only get the position of the error you can use haxe.PosInfos as the last argument of your doTest() function and pass that arguemnt to assertEquals() like this:
import haxe.unit.TestCase;
class Main {
static function main() {
var r = new haxe.unit.TestRunner();
r.add(new Test());
r.run();
}
}
class Test extends TestCase {
public function new() {
super();
}
public function testExample() {
doTest(1, 1);
doTest(1, 2);
doTest(3, 3);
}
function doTest(a:Int, b:Int, ?pos:haxe.PosInfos) {
assertEquals(a, b, pos);
}
}
Online example here
It will give you the position that called doTest() in the error:
Test::testExample() ERR: Main.hx:18(Test.testExample) - expected '1' but was '2'
Another option if you want to add a custom message is to catch the assertEquals() error and rethrow the currentTest with a custom error like this:
import haxe.unit.TestCase;
class Main {
static function main() {
var r = new haxe.unit.TestRunner();
r.add(new Test());
r.run();
}
}
class Test extends TestCase {
public function new() {
super();
}
public function testExample() {
doTest(1, 1, "Error on test 1");
doTest(1, 2, "Error on test 2");
doTest(3, 3, "Error on test 3");
}
function doTest(a:Int, b:Int, errorMsg:String, ?pos:haxe.PosInfos) {
try {
assertEquals(a, b, pos);
} catch(e:Dynamic) {
currentTest.error = errorMsg;
throw currentTest;
}
}
}
Online example here
Which will give you the following error:
Test::testExample() ERR: Main.hx:18(Test.testExample) - Error on test 2
You are effectively blending multiple tests into a single one. And Haxe cannot tell where your array element is defined (line number, etc)
What I suggest is to change the signature of doTest to accept Array<Int> instead of Array<Array<Int>> and call doTest multiple times instead of just once. Together with the suggestion from Justo, passing the pos object to assetEquals, you will get the position correctly.

When using Moq Verify() method invocation count, have failing test's error message contain actual method invocation count using Moq

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