Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to execute method on component? #80

Closed
robalexclark opened this issue Mar 31, 2020 · 2 comments
Closed

How to execute method on component? #80

robalexclark opened this issue Mar 31, 2020 · 2 comments

Comments

@robalexclark
Copy link

What is the correct way to execute a method on a component? For example I have a MessageBox component, which builds on the Blazorise Modal dialog.

@code {
    private string title;
    private string message;

    // reference to the modal component
    private Modal messageBoxModal;

    public void ShowMessageBox(string title, string message)
    {
        this.title = title;
        this.message = message;

        messageBoxModal.Show();
    }

    private void CloseMessageBox()
    {
        messageBoxModal.Hide();
    }
}

I'm trying to test "ShowMessageBox" as follows:

....
            var mb = cut.Instance;
            mb.ShowMessageBox("Test Title", "Test message");

But this results in the following error:
'The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.'

Is this a issue with the way I am testing, the bUnit library or the fact that the Blazorise modal probably uses some fancy async / Invoke methodology?

@egil
Copy link
Member

egil commented Mar 31, 2020

@robalexclark good question.

Right now with beta-6, you can do the following (I think, not tested):

public void Test()
{
    var cut = RenderComponent<MessageBox>();
    
    Renderer.Dispatcher.InvokeAsync(() => cut.Instance.ShowMessageBox("Test Title", "Test message"));

    // ... do assertions
}

Alternatively, I think you can change your component to do the following:

    public void ShowMessageBox(string title, string message)
    {
        this.title = title;
        this.message = message;
        InvokeAsync(() => messageBoxModal.Show());
    }

A little background: The reason this problem shows up is because the renderer, which re-renders the component when you ShowMessageBox, runs on a different thread than the test runs. The same problem can occur in a production environment, e.g. if you have a timer that triggers something in a component. Here is a bit more background on this: https://cloudscopeph.com/blazor-exception-current-thread-is-not-associated-with-the-renderers-synchronization-context/

In a future version of the library, I think it would be a good idea to add the InvokeAsync method to e.g. the test context you are executing the tests in, making it easier to do what I show in the test example above.

If this solves the problem, please let me know and close the issue if you are happy with the solution.

@robalexclark
Copy link
Author

Renderer.Dispatcher.InvokeAsync does resolve the issue - thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants