I have react18 (typescript) app and want to test it with cypress 10.
I wrote e2e cypress, and for some reason I have to stub one method - regular method, not network call.
the method I want to stub:
export class UserUtil {
public async init() {
...
}
}
const userUtil = new UserUtil();
export default userUtil;
I'm trying to stub it beforeEach test:
import userUtil from '../../../userUtil';
beforeEach(() => {
cy.stub(userUtil, 'init').as('init');
cy.visit('/');
}
I can see the stub in the stub list:
but actually it has no calls. in dev tools I can see the original code is called.
I tried to stub different type of methods (static, arrow functions) and nothing worked.
maybe I can't do it on e2e tests this way?
(I have component test with stubbing and it works well)
Related
I am testing a service which heavily relies on project reactor.
For many tests I am mocking the return value of the component responsible for API calls.
The tests are split over multiple files.
When I run the tests of one file, they are green, but when I execute all of the test files at once, some tests fail, with the error message indicating that the mocking did not succeed (Either the injected component returned null, or the implementation of the actual component is invoked).
In the logs, there is no information about the mocking failing.
A code example:
interface API {
Flux<Bird> getBirds();
}
#Component
class BirdWatcher {
API api;
BirdWatcher(API api) {
this.api = api;
}
Flux<Bird> getUncommonBirds() {
return api.getBirds() // Although this is mocked in the test, in some runs it returns `null` or calls the implementation of the actual component
.filter(Bird::isUncommon);
}
}
#SpringBootTest
class BirdWatcherTests {
#Autowired
BirdWatcher birdWatcher;
#MockBean
API api;
#Test
void findsUncommonBirds() {
// Assemble
Bird birdCommon = new Bird("Sparrow", "common");
Bird birdUncommon = new Bird("Parrot", "uncommon");
Mockito.when(api.getBirds()).thenReturn(Flux.just(birdCommon, birdUncommon));
// Act
Flux<Bird> uncommonBirds = birdWatcher.getUncommonBirds();
// Assert
assertThat(uncommonBirds.collectList().block().size(), equalTo(1));
}
}
For me the issue seems like a race condition, but I don't know where and how this might happen, and how I can check and fix this.
I am using spring-boot-test:2.7.8, pulling in org.mockito:mockito-core:4.5.1 org.mockito:mockito-junit-jupiter:4.5.1, and org.junit.jupiter:junit-jupiter:5.8.2, with gradle 7.8.
For reactor, spring-boot-starter-webflux:2.7.8, depending on reactor:2.7.8.
I'm writting a test case which need to mock a static method:
public function test_process_verify_card_succeed()
{
// Mock MqttClient
$this->mock('alias:' . MqttClient::class, function (MockInterface $mock) {
$mock->shouldReceive('publishVerifiedCardMessage')->once()
->with('project/controller_01/command', [2, 3], 10)
->andReturn('Some json encoded data');
});
// ...some logics and assertions
}
This test run & assert as expected. Even when I run all tests on this class, it still successes:
But when I run test all my tests, some tests failed (even they passed before) and all of failed tests are api tests which return success code
And all errors return are:
PHPUnit\Framework\ExceptionWrapper
Call to a member function __call() on null
at vendor/phpunit/phpunit/phpunit:98
94▕ unset($options);
95▕
96▕ require PHPUNIT_COMPOSER_INSTALL;
97▕
➜ 98▕ PHPUnit\TextUI\Command::main();
99▕
If I remove alias: before my test above, these test failed but all other tests pass.
Note that before these test with static method above was written, all tests pass
I think each test run individually and I dont' understand why this happend.
I am trying to set up on my cypress framework a way to, on every test scenario, execute some actions, among them a cy.request.
My beforeEach.js file is somewhere along these lines:
import { Actor, Action } from "cypress-screenplay";
import * as auth from "../../../../../support/ui/auth";
new Actor().perform(auth.uiLogin);
(the Actor object ultimately executes a cy.request) to perform a log in via API).
Then with the simplest test, I get the following message:
The following error originated from your test code, not from Cypress.
> Cannot call cy.request() outside a running test.
This usually happens when you accidentally write commands outside an it(...) test.
If that is the case, just move these commands inside an it(...) test.
How else can I solve this problem?
I do not want to include the contents of the beforeEach on another step of my cucumber test as it would add quite a lot of noise (one line per test, on 100 tests...)
beforeEach() is a hook - a function call - not a file. In /cypress/support/index.js add
import { Actor, Action } from "cypress-screenplay";
import * as auth from "./ui/auth";
beforeEach(() => {
new Actor().perform(auth.uiLogin)
})
This will run your login before every test.
One problem though, the usage for screenplay shows
const actor = new Actor();
at the top of the test, and the actor logged in should be the same actor tested.
You can perhaps use a custom command instead,
/cypress/support/index.js
import { Actor, Action } from "cypress-screenplay";
import * as auth from "./ui/auth";
Cypress.Commands.add('loginNewActor', () => {
const actor = new Actor()
actor.perform(auth.uiLogin)
return actor
})
test
let actor
beforeEach(() => {
actor = cy.loginNewActor()
})
Is there as simple as dependsonmethods used in test annotations in testNG equivalent in cypress?
example if in selenium test annotations it looks like this?
#Test()
public void tc1(){
}
#Test(dependsOnMethods= {"tc1"})
public void tc2(){
}
#Test(dependsOnMethods= {"tc1"})
public void tc3(){
}
if I am not mistaken this is somewhat like a parent function with 2 child functions that when the parent conditions inside is error then the two child functions will be skip.
in cypress I know there is callbacks and promise but depending on the kind of assertion you want it becomes more complex to me. I am new to cypress
please let me know if not too much to ask, can you at least provide an example
thanks
Cypress doesn't have dependsOnMethods like TestNG runner provides as both of them are different. But whatever you want to achieve, you can achieve through hooks provided by Mocha, as Cypress has Mocha as a test framework in itself.
Note: This is what all you can do with hooks and your problem should be solved with below code. If you have any specific requirement, please mention it.
describe('test suite', () => {
before(() => {})
beforeEach(() => { // put tc1() functionality
})
it('tc2 functionality', () => {
// now tc2() depends on beforeEach block where tc1 functionality is done
})
it('tc3 functionality', () => {
// now tc3() depends on beforeEach block where tc1 functionality is done
})
})
I'm writing a unit test for a Flutter method that calls an async method and then returns, leaving the async to complete as and when. My test fails "after it had already completed".
Here's my test:
test('mark as viewed', () {
final a = Asset();
expect(a.viewed, false);
a.markAsViewed();
expect(a.viewed, true);
});
and here's the method it's testing:
void markAsViewed() {
viewed = true;
Repository.get().saveToStorage();
}
The saveToStorage() method is an async that I just leave to execute in the background.
How do I make this work? The test failure tells me Make sure to use [expectAsync] or the [completes] matcher when testing async code. but I can't see how to do that. Can anyone explain or else point me to the right documentation please? I can't find anything about how to handle these asyncs when it's not a Future that's being returned, but just being left to complete separately.
To be clear - this unit test isn't about testing whether it's saved to storage, just a basic test on setting viewed to be true.
Edited
The error is as follows:
package:flutter/src/services/platform_channel.dart 319:7 MethodChannel.invokeMethod
===== asynchronous gap ===========================
dart:async _asyncErrorWrapperHelper
package:exec_pointers/asset_details.dart Repository.saveToStorage
package:exec_pointers/asset_details.dart 64:22 Asset.markAsViewed
test/asset_details_test.dart 57:9 main.<fn>.<fn>
This test failed after it had already completed. Make sure to use [expectAsync]
or the [completes] matcher when testing async code.
This code is tightly coupled to implementation concerns that make testing it in isolation difficult.
It should be refactored to follow a more SOLID design with explicit dependencies that can be replaced when testing in isolation (unit testing)
For example
class Asset {
Asset({Repository repository}) {
this.repository = repository;
}
final Repository repository;
bool viewed;
void markAsViewed() {
viewed = true;
repository.saveToStorage();
}
//...
}
That way when testing a mock/stub of the dependency can be used to avoid any unwanted behavior.
// Create a Mock Repository using the Mock class provided by the Mockito package.
// Create new instances of this class in each test.
class MockRepository extends Mock implements Repository {}
main() {
test('mark as viewed', () {
final repo = MockRepository();
// Use Mockito to do nothing when it calls the repository
when(repo.saveToStorage())
.thenAnswer((_) async => { });
final subject = Asset(repo);
expect(subject.viewed, false);
subject.markAsViewed();
expect(subject.viewed, true);
//
verify(repo.saveToStorage());
});
}
The test should now be able to be exercised without unexpected behavior from the dependency.
Reference An introduction to unit testing
Reference Mock dependencies using Mockito
Reference mockito 4.1.1