Giter Site home page Giter Site logo

Comments (12)

egil avatar egil commented on July 23, 2024

Since it is the Submit() call that triggers an async operation, which causes a render, your best option is currently to use the WaitForNextRender helper method in the framework. E.g.

WaitForNextRender(() => cut.Find("form").Submit());

Check out WikiSearch example or the FetchData example in the Wiki for more examples of how to use WaitForNextRender:

Note, that the WaitForNextRender will only wait for one render. If your async logic causes multiple renders before the expected changes are visible, it will not be enough. I am actively working on a solution for that, see this PR if you are interested in following along: #59

from bunit.

jpiell avatar jpiell commented on July 23, 2024

The PR you are working on might fix this.

I tried WaitForNextRender. It did not work. I think the Test method is blocking the async task from running.

from bunit.

egil avatar egil commented on July 23, 2024

Tests run in the xunit synchronization context, and the renderer, and thus the async code you have, run in the renderer's dispatcher's context. That said, when you do Task.Run, it is running in an entirely new thread, and I am not sure which sync context it gets attached to. I generally do not recommend using Task.Run like that in your components.

Take a look at the samples I liked to above to see if these do not match your scenario. Otherwise, yes, you would have to wait for the next release of the library, or roll your own custom async waiter.

from bunit.

jpiell avatar jpiell commented on July 23, 2024

I only used Task.Run to simulate what happens with a SaveAsync OnValidSubmit="SaveAsync".

Any way you make SaveAsync an aync Task will recreate the problem.

The xunit syncronization context has to complete before the SaveAsync will be dispatched.

I think the RenderComponent needs to be awaited as to not block the SaveAsync from being dispatched.

Will the issue you are working on the the next version address this?

Thanks,

Jeff

from bunit.

jpiell avatar jpiell commented on July 23, 2024

You can see the issue by placing a break point in SaveAsync and on the assert so you can see which order methods are called.

from bunit.

egil avatar egil commented on July 23, 2024

Most likely. From your small sample, there are certainly some things I would do differently. Like not injecting a concrete class in your FetchData, but instead an IWeatherForcastService, that you can mock. That way you can control when and during the lifecylce of the test, the forecasts are returned to the component.

Take a look at the sample TodoList test in the Samples folder, it shows this approach.

from bunit.

jpiell avatar jpiell commented on July 23, 2024

I don't thing my question is about what I can do different. It is about the threading model being used in the library. Please keep in mind I cannot share the actual code being tested so I put together small examples that demonstrate an issue.

When a form is submitted and OnValidSubmit calls an aysnc Task, the task will not be dispatched until the xunit thread completes. I beleive this is because the thread is being blocked by not having an await on the calling thread. If there was a RenderComponentAsync that did an await, the child threads would run and the RenderComponent would wait until the child thread completes.

This is demonstrated by setting a break point in the SaveAsync method that is called OnValidSubmit and another break point on the assert so that you can see the SaveAsync method isn't called until the test thread is complete.

from bunit.

egil avatar egil commented on July 23, 2024

Hmm I an not sure I can replicate the issue. RenderComponent should block until the first render of the component under test is completed. When I download your sample and just run the test, everything is green. What missing?

C:\Users\egh\Downloads\BlazorApp1 (2)\BlazorApp1\BlazorApp1> ls


    Directory: C:\Users\egh\Downloads\BlazorApp1 (2)\BlazorApp1\BlazorApp1


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       18-02-2020     17:18                BlazorApp1
d-----       18-02-2020     17:18                ComponentTests
-a----       18-02-2020     17:18           1632 BlazorApp1.sln


C:\Users\egh\Downloads\BlazorApp1 (2)\BlazorApp1\BlazorApp1> dotnet test
Test run for C:\Users\egh\Downloads\BlazorApp1 (2)\BlazorApp1\BlazorApp1\ComponentTests\bin\Debug\netcoreapp3.1\ComponentTests.dll(.NETCoreApp,Version=v3.1)
Microsoft (R) Test Execution Command Line Tool Version 16.3.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.

Test Run Successful.
Total tests: 1
     Passed: 1
 Total time: 3,3801 Seconds

from bunit.

jpiell avatar jpiell commented on July 23, 2024

If you put break points where I said, you will see that the SaveAsync is not called until after the Assert and the test method is completed. The SaveAsync should be called after the submit is performed.

from bunit.

egil avatar egil commented on July 23, 2024

When I run your test in your sample (on a dual core, four thread laptop), the first breakpoint it hits, is the one in line 21 in FetchDataTest.cs, then it hits the breakpoint on line 23 in the same class, and then the breakpoint in FetchData on line 81. Is that also what you are seeing?

If I change the test to this, which will be possible in the next version of the library, the breakpoint on Assert.True(cut.Instance.saved) isnt hit before after SaveAsync has completed:

[Fact]
public void FetchDataRendersCorrectly()
{
    Services.AddSingleton<WeatherForecastService>();

    var cut = RenderComponent<FetchData>();
            
    cut.Find("#Summary_textbox").Change("test");
    cut.Find("form").Submit();
    cut.WaitForState(() => cut.Instance.saved);

    Assert.True(cut.Instance.saved);
}

This still doesnt have anything to do with the RenderComponent method though, as far as I can see.

from bunit.

jpiell avatar jpiell commented on July 23, 2024

Your description above of the actions is correct. I the WaitForState will allow the component thread to run as you stated, then yes that will address the issue.

Any idea when the next version with the WaitForState will be pushed?

from bunit.

egil avatar egil commented on July 23, 2024

Your description above of the actions is correct. I the WaitForState will allow the component thread to run as you stated, then yes that will address the issue.

WaitForState will wait (block) the test thread until the predicate you pass to it returns true (or a timeout is passed). So that may include zero or more renders in the render thread.

WaitForNextRender only waits (block) the test thread for one render on the render thread, or until a timeout is passed. So if your logic requires you to wait for multiple renders, then you cannot use that.

Any idea when the next version with the WaitForState will be pushed?

Hopefully within a week, maybe two.

from bunit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.