Why is #BeforeSuite variable sometimes initialised correctly in test, and other times null? - automated-tests

I'm trying to use the #BeforeSuite annotation in my tests to create some Data that will be used across all tests, therefore I only want to create it once and then be able to access it from all of my tests that run.
I'm seeing an issue where, SOMETIMES, my data gets created and is accessible within my tests, and other times the data is created but the data object is null when the test is executing.
Why would it only work sometimes and not others?
Here are my slimmed down pieces of relevant code.
class DataSetup {
#Synchronized
fun getData(): DataProfile {
var user: User("Bill", "Smyth")
var address: Address("123 Fake St", "Australia")
return DataProfile(user, address)
}
fun printDataProfile(profile: DataProfile) {
println(
"DataProfile:: User: ${user.name}"
}
}
data class DataProfile(
var user: User,
var address: Address
)
I have another base class where I do the setup within a #BeforeSuite method.
open class TestBase {
lateinit var profile: DataProfile
#BeforeSuite(enabled = true, groups = ["smoke", "regression"])
fun create_data(testContext: ITestContext) {
profile = DataSetup().getData()
My test file then inherits from this base class.
class UserDetailsTest : TestBase() {
#Test(description = "Check User Details", groups = ["regression"])
fun givenCheckList_WhenRetrieved_ThenReturns200() {
println(profile) // THIS IS SOMETIMES NULL, WHY??
}
}
The gradle task I have defined in my build.gradle file.
tasks.register<Test>("regression") {
useTestNG() {
testLogging.showStandardStreams = true
includeGroups ("regression")
}
}
Is this the correct way to go about using shared data between tests? Or should I be using ITestContext in all of my test files?
This is all still very new to me so any help to understand is much appreciated!

Related

Unable to mock FullCalendar's getApi() that returns a mock Calendar (Angular & Jasmine, Karma)

I'm trying to write test cases around a component that contains my FullCalendar component in Angular.
I've written karma tests using a MockFullCalendar that extends FullCalendar and have been successfully able to mock the getApi().view calls for getting fake active start and active end dates. But when I use the same method for getApi().getResources() and getApi.getResourceById(id) I get this error when running tests
error TS2339: Property 'getResourceById' does not exist on type 'Calendar'.
const calendarResource = this.calendar.getApi().getResourceById(resourceIdAssignedToEvent);
Here are my mock classes
export class MockFullCalendarComponent extends FullCalendarComponent {
getApi(): any {
return {};
}
}
export class MockCalendarApi extends CalendarApi {
getResources(): any {
return [];
}
getResourceById(resourceId: any): any {
return {};
}
}
export class MockCalendar extends MockCalendarApi {
get view(): any {
return {
get activeStart(): any {
return new Date();
},
get activeEnd(): any {
return new Date();
}
};
}
}
The following is how I was able to successfully mock the getApi().view
export class MockFullCalendarComponent extends FullCalendarComponent {
getApi(): any {
return {
view: {
activeStart: new Date(),
activeEnd: new Date()
}
};
}
}
Using the same pattern somehow does not work for the Calendar and CalendarApi classes. I'm not sure if this is because there is a class and an interface of the same name (CalendarApi) in FullCalendar common and only the interface contains these two methods.
I'm using Angular 12 and FullCalendar V5.
I've tried mocking as described above, tried different ways to provide my mock classes to the TestBed for injection.
My test case does not run at all, because these methods aren't detected somehow, none of the existing tests run at all, its almost like the whole initialization of the test case fails at this and I'm not sure how else I can force the spec to use my mock classes that contains mock implementations of those methods.

What is the correct way of handling collect in Kotlin?

I'm getting user data from Firestore using MVVM. In the repository class I use:
fun getUserData() = flow {
auth.currentUser?.apply {
val user = ref.document(uid).get().await().toObject(User::class.java)
user?.let {
emit(Success(user))
}
}
}. catch { error ->
error.message?.let { message ->
emit(Failure(message))
}
}
This method is called from the ViewModel class:
fun getUser() = repo.getUserData()
And in the activity class I use:
private fun getUser() {
lifecycleScope.launch {
viewModel.getUser().collect { data ->
when(data) {
is Success -> textView.text = data.user.name
is Failure -> print(data.message)
}
}
}
}
To display the name in the TextView. The code works fine. But is this the correct way if doing things? Or is it more correct to collect the data in the ViewModel class?
Any room for improvement? Thanks
My personal opinion is that data should be collected in the VM so it survives configuration changes.
The scope of the view (activity/fragment) should not drive your data flow.
The VM will outlive activities and fragments during configuration changes, so all the data you have collected and transformed, will still be there (or in progress if it's still being obtained).
StateFlow is good (in this last step) because it has the ability to tell the VM: This is no longer needed, don't waste resources.
But I haven't yet used StateFlow in production code so there's that.

How to use properly EntityRepository instances?

The documentation stresses that I should use a new EntityManager for each request and there's even a middleware for automatically generating it or alternatively I can use em.fork(). So far so good.
The EntityRepository is a great way to make the code readable. I could not find anything in the documentation about how they relate to EntityManager instances. The express-ts-example-app example uses single instances of repositories and the RequestContext middleware. This suggests that there is some under-the-hood magic that finds the correct EntityManager instances at least with the RequestContext. Is it really so?
Also, if I fork the EM manually can it still find the right one? Consider the following example:
(async () => {
DI.orm = await MikroORM.init();
DI.em = DI.orm.em;
DI.companyRepository = DI.orm.em.getRepository(Company);
DI.invoiceRepository = DI.orm.em.getRepository(Invoice);
...
fetchInvoices(em.fork());
}
async function fetchInvoices(em) {
for (const company of await DI.companyRepository.findAll()) {
fetchInvoicesOfACompany(company, em.fork())
}
}
async function fetchInvoicesOfACompany(company, em) {
let done = false;
while (!done) {
const invoice = await getNextInvoice(company.taxnumber, company.lastInvoice);
if ( invoice ) {
DI.invoiceRepository.persist(invoice);
company.lastInvoice = invoice.id;
em.flush();
} else {
done = true;
}
}
}
Does the DI.invoiceRepository.persist() in fetchInvoicesOfACompany() use the right EM instance? If not, what should I do?
Also, if I'm not mistaken, the em.flush() in fetchInvoicesOfACompany() does not update company, since that belongs to another EM - how should I handle situations like this?
First of all, repository is just a thin layer on top of EM (an extension point if you want), that bares the entity name so you don't have to pass it to the first parameter of EM method (e.g. em.find(Ent, ...) vs repo.find(...).
Then the contexts - you need a dedicated context for each request, so it has its own identity map. If you use RequestContext helper, the context is created and saved via domain API. Thanks to this, all the methods that are executed inside the domain handler will use the right instance automatically - this happens in the em.getContext() method, that first checks the RequestContext helper.
https://mikro-orm.io/docs/identity-map/#requestcontext-helper-for-di-containers
Check the tests for better understanding of how it works:
https://github.com/mikro-orm/mikro-orm/blob/master/tests/RequestContext.test.ts
So if you use repositories, with RequestContext helper it will work just fine as the singleton repository instance will use the singleton EM instance that will then use the right request based instance via em.getContext() where approapriate.
But if you use manual forking instead, you are responsible use the right repository instance - each EM fork will have its own one. So in this case you can't use a singleton, you need to do forkedEm.getRepository(Ent).
Btw alternatively you can also use AsyncLocalStorage which is faster (and not deprecated), if you are on node 12+. The RequestContext helper implementation will use ALS in v5, as node 12+ will be requried.
https://mikro-orm.io/docs/async-local-storage
Another thing you could do is to use the RequestContext helper manually instead of via middlewares - something like the following:
(async () => {
DI.orm = await MikroORM.init();
DI.em = DI.orm.em;
DI.companyRepository = DI.orm.em.getRepository(Company);
DI.invoiceRepository = DI.orm.em.getRepository(Invoice);
...
await RequestContext.createAsync(DI.em, async () => {
await fetchInvoices();
})
});
async function fetchInvoices() {
for (const company of await DI.companyRepository.findAll()) {
await fetchInvoicesOfACompany(company)
}
}
async function fetchInvoicesOfACompany(company) {
let done = false;
while (!done) {
const invoice = await getNextInvoice(company.taxnumber, company.lastInvoice);
if (invoice) {
company.lastInvoice = invoice; // passing entity instance, no need to persist as `company` is managed entity and this change will be cascaded
await DI.em.flush();
} else {
done = true;
}
}
}

How to test the method passed to subscribe method of the PubSubEvent in the Wpf Prism library?

I have two ViewModels, MainWindowShellViewModel(shellVm) and MainWindowContentViewModel(contentVm). The shellVm publishes an event and the contentVm subscribes to it.
The shell VM looks something like the following. I have omitted many details.
// ctor
public MainWindowShellViewModel(IEventAggregator eventAggregator)
{
_EventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(IEventAggregator) + " service injected is null!!!");
_AppStartingClosingEventToken = _EventAggregator.GetEvent<AppStartingClosingEvent>();
}
private void MainWindowShellLoaded()
{
var payload = new AppStartingClosingEventData();
payload.Data = "MainWindowStarting";
_AppStartingClosingEventToken.Publish(payload);
}
The AppStartingClosingEvent is a no brainer type as follows.
public class AppStartingClosingEvent : PubSubEvent<AppStartingClosingEventData>
{ }
public class AppStartingClosingEventData
{
public string Data { get; set; }
}
And finally, the contentVm looks as follows.
public MainWindowContentViewModel(IEventAggregator eventAggregator)
{
_AppClosingEventToken.Subscribe(AppStartingClosing);
}
private void AppStartingClosing(AppStartingClosingEventData appStartingClosingEventData)
{
if (appStartingClosingEventData.Data == "MainWindowStarting")
LoadState(appStartingClosingEventData);
if (appStartingClosingEventData.Data == "MainWindowClosing")
SaveState(appStartingClosingEventData);
}
I want to test the that the method AppStartingClosing inside of contentVm is called with proper data. I am using Moq
I am running out of ideas. Please suggest. Tried the following but so far no success.
How do I test Prism event aggregator subscriptions, on the UIThread?
Using Moq to verify a Prism event subscription fails
Unit testing with Moq, Prism 6, and Event Aggregation
Moq Event Aggregator Is it possible
// Verifying a delegate was called with Moq
EDIT
Here is what I have tried.
// Arrange
var mockingKernel = new MoqMockingKernel();
var eventAggregatorMock = mockingKernel.GetMock<IEventAggregator>();
var eventBeingListenedTo = new AppStartingClosingEvent();
eventAggregatorMock.Setup(e => e.GetEvent<AppStartingClosingEvent>()).Returns(eventBeingListenedTo);
var vm = mockingKernel.Get<MainWindowContentViewModel>();
var evData = new AppStartingClosingEventData();
evData.Data = "MainWindowStarting";
// Act
eventBeingListenedTo.Publish(evData);
Now, what should I do? I am not even clear if I have approached correctly.
Now what should I do?
After eventBeingListenedTo.Publish(evData); look whether whatever effect SaveState should have is actually happening.
I am not even clear if I have approached correctly.
You do not want to test whether one method in a class is called by another method of that class.
So instead of trying to do
subjectUnderTest.DoStuff();
MagicallyVerifyThatThisGotCalled( () => subjectUnderTest.SomeEffect() );
you should do
var subjectUnderTest = new SubjectUnderTest( serviceMock.Object );
subjectUnderTest.DoStuff();
serviceMock.Verify( x => x.SomeEffectOnTheService(), Times.Once );
Assert.That( subjectUnderTest.SomePropertyThatsChanged, Is.EqualTo( newValue ) );
Whatever SubjectUnderTest does internally to achieve the desired effect, is not in the scope of the test. It's private to SubjectUnderTest, you don't care how it is done as long as it is done at all. When testing, look at the externally visible state of your subject under test, and what it does to its dependencies.

Nunit and web applications

I begin studying Unit testing with "(NUnit)". I know that this type of testing is used to test "classes" , "functions" and the "interaction between those functions".
In my case I develop "asp.net web applications".
How can i use this testing to test my
pages(as it is considered as a class
and the methods used in)and in which sequence?, i have three layers:
Interface layer(the .cs of each page).
Data access layer(class for each entity)(DAL).
Database layer (which contains connection to the database,open connection,close connection,....etc).
Business layer(sometimes to make calculation or some separate logic).
How to test the methods that make connection to the database?
How to make sure that my testing not a waste of time?.
There are unit and integration tests. Unit testing is testing single components/classes/methods/functions and interaction between them but with only one real object (system under test-SUT) and test doubles. Test doubles can be divided to stubs and mocks. Stubs provide prepared test data to SUT. That way you isolate SUT from the environment. So You don't have to hit database, web or wcf services and so on and you have same input data every time. Mocks are used to verify that SUT works as expected. SUT calls methods on mock object not even knowing it is not real object. Then You verify that SUT works by asserting on mock object. You can write stubs and mocks by hand or use one of many mocking frameworks. One of which is http://code.google.com/p/moq/
If You want to test interaction w/database that's integration testing and generally is a lot harder. For integration testing You have to setup external resources in well known state.
Let's take your layers:
You won't be able to unit test it. Page is to tightly coupled to ASP.NET runtime. You should try to not have much code in code behind. Just call some objects from your code behind and test those objects. You can look at MVC design patters. If You must test Your page You should look at http://watin.org/. It automates Your internet browser, clicks buttons on page and verifies that page displays expected result's.
This is integration testing. You put data in database, then read it back and compare results. After test or before test You have to bring test database to well known state so that tests are repeatable. My advice is to setup database before test runs rather then after test runs. That way You will be able to check what's in database after test fails.
I don't really know how that differs from that in point no. 2.
And this is unit testing. Create object in test, call it's methods and verify results.
How to test methods that make connections to the database is addresed in point 2.
How to not waste time? That will come with experience. I don't have general advice other then don't test properties that don't have any logic in it.
For great info about unit testing look here:
http://artofunittesting.com/
http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530
http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627/ref=sr_1_2?ie=UTF8&s=books&qid=1306787051&sr=1-2
http://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054/ref=sr_1_1?ie=UTF8&s=books&qid=1306787051&sr=1-1
Edit:
SUT, CUT - System or Class under test. That's what You test.
Test doubles - comes from stunt doubles. They do dangerous scenes in movies so that real actors don't have to. Same here. Test doubles replace real objects in tests so that You can isolate SUT/CUT in tests from environment.
Let's look at this class
public class NotTestableParty
{
public bool ShouldStartPreparing()
{
if (DateTime.Now.Date == new DateTime(2011, 12, 31))
{
Console.WriteLine("Prepare for party!");
return true;
}
Console.WriteLine("Party is not today");
return false;
}
}
How will You test that this class does what it should on New Years Eve? You have to do it on New Years Eve :)
Now look at modified Party class
Example of stub:
public class Party
{
private IClock clock;
public Party(IClock clock)
{
this.clock = clock;
}
public bool ShouldStartPreparing()
{
if (clock.IsNewYearsEve())
{
Console.WriteLine("Prepare for party!");
return true;
}
Console.WriteLine("Party is not today");
return false;
}
}
public interface IClock
{
bool IsNewYearsEve();
}
public class AlwaysNewYearsEveClock : IClock
{
public bool IsNewYearsEve()
{
return true;
}
}
Now in test You can pass the fake clock to Party class
var party = new Party(new AlwaysNewYearsEveClock());
Assert.That(party.ShouldStartPreparing(), Is.True);
And now You know if Your Party class works on New Years Eve. AlwaysNewYearsEveClock is a stub.
Now look at this class:
public class UntestableCalculator
{
private Logger log = new Logger();
public decimal Divide(decimal x, decimal y)
{
if (y == 0m)
{
log.Log("Don't divide by 0");
}
return x / y;
}
}
public class Logger
{
public void Log(string message)
{
// .. do some logging
}
}
How will You test that Your class logs message. Depending on where You log it You have to check the file or database or some other place. That wouldn't be unit test but integration test. In order to unit test You do this.
public class TestableCalculator
{
private ILogger log;
public TestableCalculator(ILogger logger)
{
log = logger;
}
public decimal Divide(decimal x, decimal y)
{
if (y == 0m)
{
log.Log("Don't divide by 0");
}
return x / y;
}
}
public interface ILogger
{
void Log(string message);
}
public class FakeLogger : ILogger
{
public string LastLoggedMessage;
public void Log(string message)
{
LastLoggedMessage = message;
}
}
And in test You can
var logger = new FakeLogger();
var calculator = new TestableCalculator(logger);
try
{
calculator.Divide(10, 0);
}
catch (DivideByZeroException ex)
{
Assert.That(logger.LastLoggedMessage, Is.EqualTo("Don't divide by 0"));
}
Here You assert on fake logger. Fake logger is mock object.

Resources