/discordgo-mock

Helper library to assist with writing unit tests for projects that use https://github.com/bwmarrin/discordgo

Primary LanguageGoMIT LicenseMIT

discordgo-mock

Go Reference

discordgo-mock is a helper library to assist with writing unit tests for projects that use discordgo. The library provides a custom http.RoundTripper to be injected into an *http.Client.Transport before being injected into discordgo.Session.

The custom http.RoundTripper maps the Discord REST API methods and paths to appropriate handler functions and returns expected data based upon what is in the provided discordgo.State cache. Discord API calls that involve creating new, updating, or deleting resources will also update the internal discordgo.State cache to maintain state changes.

Example Usage

package mocksession_test

import (
	"net/http"
	"testing"

	"github.com/bwmarrin/discordgo"
	"github.com/ewohltman/discordgo-mock/mockchannel"
	"github.com/ewohltman/discordgo-mock/mockconstants"
	"github.com/ewohltman/discordgo-mock/mockguild"
	"github.com/ewohltman/discordgo-mock/mockmember"
	"github.com/ewohltman/discordgo-mock/mockrest"
	"github.com/ewohltman/discordgo-mock/mockrole"
	"github.com/ewohltman/discordgo-mock/mocksession"
	"github.com/ewohltman/discordgo-mock/mockstate"
	"github.com/ewohltman/discordgo-mock/mockuser"
)

func TestNew(t *testing.T) {
	state, err := newState()
	if err != nil {
		t.Fatal(err)
	}

	session, err := mocksession.New(
		mocksession.WithState(state),
		mocksession.WithClient(&http.Client{
			Transport: mockrest.NewTransport(state),
		}),
	)
	if err != nil {
		t.Fatal(err)
	}

	guildBefore, err := session.Guild(mockconstants.TestGuild)
	if err != nil {
		t.Fatal(err)
	}

	t.Logf("Name: %s", guildBefore.Name)
	t.Logf("Channels: %d", len(guildBefore.Channels))
	t.Logf("Members: %d", guildBefore.MemberCount)

	t.Logf("Roles before change: %d", len(guildBefore.Roles))

	_, err = session.GuildRoleCreate(guildBefore.ID)
	if err != nil {
		t.Fatal(err)
	}

	guildAfter, err := session.Guild(mockconstants.TestGuild)
	if err != nil {
		t.Fatal(err)
	}

	t.Logf("Roles after change: %d", len(guildAfter.Roles))
}

func newState() (*discordgo.State, error) {
	role := mockrole.New(
		mockrole.WithID(mockconstants.TestRole),
		mockrole.WithName(mockconstants.TestRole),
		mockrole.WithPermissions(discordgo.PermissionViewChannel),
	)

	botUser := mockuser.New(
		mockuser.WithID(mockconstants.TestUser+"Bot"),
		mockuser.WithUsername(mockconstants.TestUser+"Bot"),
		mockuser.WithBotFlag(true),
	)

	botMember := mockmember.New(
		mockmember.WithUser(botUser),
		mockmember.WithGuildID(mockconstants.TestGuild),
		mockmember.WithRoles(role),
	)

	userMember := mockmember.New(
		mockmember.WithUser(mockuser.New(
			mockuser.WithID(mockconstants.TestUser),
			mockuser.WithUsername(mockconstants.TestUser),
		)),
		mockmember.WithGuildID(mockconstants.TestGuild),
		mockmember.WithRoles(role),
	)

	channel := mockchannel.New(
		mockchannel.WithID(mockconstants.TestChannel),
		mockchannel.WithGuildID(mockconstants.TestGuild),
		mockchannel.WithName(mockconstants.TestChannel),
		mockchannel.WithType(discordgo.ChannelTypeGuildVoice),
	)

	privateChannel := mockchannel.New(
		mockchannel.WithID(mockconstants.TestPrivateChannel),
		mockchannel.WithGuildID(mockconstants.TestGuild),
		mockchannel.WithName(mockconstants.TestPrivateChannel),
		mockchannel.WithType(discordgo.ChannelTypeGuildVoice),
		mockchannel.WithPermissionOverwrites(&discordgo.PermissionOverwrite{
			ID:   botMember.User.ID,
			Type: discordgo.PermissionOverwriteTypeMember,
			Deny: discordgo.PermissionViewChannel,
		}),
	)

	return mockstate.New(
		mockstate.WithUser(botUser),
		mockstate.WithGuilds(
			mockguild.New(
				mockguild.WithID(mockconstants.TestGuild),
				mockguild.WithName(mockconstants.TestGuild),
				mockguild.WithRoles(role),
				mockguild.WithChannels(channel, privateChannel),
				mockguild.WithMembers(botMember, userMember),
			),
		),
	)
}

Output:

=== RUN   TestNew
    mocksession_test.go:40: Name: testGuild
    mocksession_test.go:41: Channels: 2
    mocksession_test.go:42: Members: 2
    mocksession_test.go:44: Roles before change: 1
    mocksession_test.go:56: Roles after change: 2
--- PASS: TestNew (0.00s)
PASS