dismock

module
v1.3.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2020 License: MIT

README ยถ

dismock

GitHub Workflow Status codecov Go Report Card godoc GitHub


Dismock is a library that aims to make mocking Discord's API requests as easy as winking. No more huge integration tests that require a bot on some private server with little to no debug information.

Dismock is not limited to a specific Discord library, although it uses arikawa as a foundation for its datatypes.

Getting Started

Basic Testing

Creating a mock is done, by calling the respective mock method, that belongs to the API request you made in your code. Below is a basic example of a ping command and it's unit test.

func (b *Bot) Ping(e *gateway.MessageCreateEvent) (error) {
    _, err := b.Ctx.SendText(e.ChannelID, "๐Ÿ“")
    if err != nil {
        return err
    }

    _, err := b.Ctx.SendText(e.ChannelID, "Pong!")
    
    return err
}
func TestBot_Ping(t *testing.T) {
    m, s := dismock.NewState(t)
    // if you want to use a Session and no State write:
    // m, s := dismock.NewSession(t)

    var channelID discord.ChannelID = 123

    m.SendText(discord.Message{
        // from the doc of Mocker.SendText we know, that ChannelID and Content
    	// are required fields, all other fields that aren't used by our function 
    	// don't need to be filled
        ChannelID: channelID,
        Content: "๐Ÿ“",
    })

    // make sure that API calls on the same endpoint with the same method are
    // added in the correct order
    m.SendText(discord.Message{
        ChannelID: channelID,
        Content: "Pong!"
    })

    b := NewBot(s)

    b.Ping(&gateway.MessageCreateEvent{
        Message: discord.Message{
            ChannelID: channelID,
        }
    })

    // at the end of every test Mocker.Eval must be called, to check for
    // uninvoked handlers and close the mock server
    m.Eval()
}
Advanced Testing

Now imagine a bit more complicated test, that has multiple sub-tests:

func (b *Bot) Ping(e *gateway.MessageCreateEvent) (error) {
    _, err := b.Ctx.SendText(e.ChannelID, "๐Ÿ“")
    if err != nil {
        return err
    }

    _, err := b.Ctx.SendText(e.ChannelID, e.Author.Mention()+" Pong!")
    
    return err
}
func TestBot_Ping(t *testing.T) {
    m := dismock.New(t)

    var channelID discord.ChannelID = 123

    m.SendText(discord.Message{
        ChannelID: channelID,
        Content: "๐Ÿ“",
    })
    
   t.Run("test1", func(t *testing.T) {
        // If you have multiple tests that have the same basic API requests,
        // you can create a mocker, add those API calls, and create a clone
        // of the mocker in every sub-test you have.
        // Cloned mockers have a copy of it's parents request, but run their
        // own mock server and have a dedicated Session/State.
        m, s := m.CloneState(t)

        ...
    })

    t.Run("test2", func(t *testing.T) {
        m, s := m.CloneState(t)
        
        ...
    })
}
Using a Different Discord Library

Because the mocking is done on a network level, you are not limited to arikawa for mocking. When creating a Mocker just use dismock.New and use the http.Client of the mocker as client for a library of your choice.

m := dismock.New(t)

s, _ := discordgo.New("Bot abc") // the token doesn't have to be valid
s.Client = m.Client

That's it!

Meta Requests

Besides regular calls to the API you can also mock requests for metadata, i.e. images such as guild icons (Mocker.GuildIcon). In order for this to work, you need to use the http.Client found in the Mocker struct, so that the mock server will be called, instead of Discord.

Directories ยถ

Path Synopsis
internal
pkg
dismock
Package dismock creates mocks for the Discord API.
Package dismock creates mocks for the Discord API.
tools
codegen/mock Module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL