techo

package module
v0.0.0-...-02c1823 Latest Latest
Warning

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

Go to latest
Published: Sep 24, 2023 License: MIT Imports: 12 Imported by: 0

README

techo

Echo-based alternative to http.httptest

techo is a package for transparently mocking HTTP/REST servers, inline in your test code, just like http.httptest. The key difference is that techo is based on Echo, which makes writing tests cleaner and more expressive.

Note The techo package was created way back in the early days of Echo. Since then there have been multiple major version releases of Echo (v4 at the time of writing). This package hasn't been updated in that time, so it may not work with recent Echo releases. I may update it if I find myself working directly with Echo again, but in the meantime, please consider this package effectively archived.

Also:

  • test multiple endpoints using the same techo instance
  • specify a particular interface/port
  • provide your own TLS certs

Here's how you might use the thing:

func TestHello(t *testing.T) {

	te := techo.New() // start the web server - it's running on some random port now
	defer te.Stop() // stop the server at the end of this function
	
	// just for fun, check what random port we're running on
	fmt.Println("My port: ", te.Port)
	
	// serve up some content (using echo, cuz it's so hot right now)
	te.GET("/hello", func(c echo.Context) error {
		param := c.QueryParam("name")
		assert.Equal(t, param, "World") // assert some stuff
		return c.String(http.StatusOK, fmt.Sprintf("Hello %v", param))
	})

	// Let's make a request to the web server
	resp, _ := http.Get(te.AbsURL("/hello?name=World"))
	// Note that te.AbsURL() turns "/hello" into "http://127.0.0.1:[PORT]/hello"
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	assert.Equal(t, "Hello World", string(body))
}

Referencing the example above, here's a few things that are going on.

  • The te object (of type techo.Techo) returned bytecho.New() has an embedded Echo server.
    • So you can treat techo.Techo just like echo.Echo, and do things like te.POST( ... ) etc.
  • When techo.New() is called, the server is started automatically...
    • on its own goroutine (transparently to the caller)
    • on a random available port
  • The base URL of the server (e.g. http://127.0.0.1:53012) is accessible via te.URL, and the port at te.Port.
  • There's a handy function for getting the URL of a path on the techo server. Just do te.AbsURL("/my/path"), and you'll get back something like http://127.0.0.1:52713/my/path.
  • Stop the server using te.Stop(). A common idiom is defer te.Stop() immediately after the call to techo.New(). FYI, the stoppability is due a (hidden) Graceful server.

Examples

Start a server at a specific address:

	cfg := &techo.Config{Addr: "localhost:6666")}
	te, err := techo.NewWith(cfg)
	if err != nil {
		return fmt.Errorf("Probably that port is in use: %v", err)
	}
	te.GET("/hello", func(c echo.Context) error {
		return c.String(http.StatusOK, "hello world")
	})

To add multiple endpoints:

	te.GET("/callme", func(c echo.Context) error {
		return c.String(http.StatusOK, "maybe")
	})

	te.GET("/goodbye", func(c echo.Context) error {
		return c.String(http.StatusOK, "goodbye cruel world")
	})
	

Start a TLS (HTTPS) server:

	te := techo.NewTLS()
	defer te.Stop()
	te.GET("/hello", func(c echo.Context) error {
		return c.String(http.StatusOK, "hello world")
	})

To set the default certs for new TLS servers:

	cert, _ := ioutil.ReadFile("path/to/server.crt")
	key, _ := ioutil.ReadFile("path/to/server.key")
	techo.SetDefaultTLSCert(cert, key)
	te := techo.NewTLS()

Or for one-time use of your own certs:

	cert, _ := ioutil.ReadFile("path/to/server.crt")
	key, _ := ioutil.ReadFile("path/to/server.key")
	cfg := &techo.Config{TLS: true, TLSCert: cert, TLSKey: key}
	te, err := techo.NewWith(cfg)

Tip: if your client uses http.DefaultClient as its underlying client, and you are using TLS, you will likely want to skip verification of the cert before any requests to the techo endpoint. techo provides a convenience method to do so.

	techo.SkipDefaultClientInsecureTLSVerify()
	// then just use your http client as per usual, no more "invalid cert" errors
	resp, err = http.Get(te.AbsURL("/hello"))
Acknowledgements

These guys do all the magic behind the scenes.

Documentation

Overview

Package techo is equivalent to http.httptest, but uses labstack/echo for greater ease of use, and provides several additional useful things.

For more, visit: https://github.com/neilotoole/techo

Example:

func TestHello(t *testing.T) {

	te := techo.New()
	defer te.Stop()
	te.GET("/hello", func(c echo.Context) error {
		param := c.QueryParam("name")
		assert.Equal(t, param, "World")
		return c.String(http.StatusOK, fmt.Sprintf("Hello %v", param))
	})

	resp, err := http.Get(te.AbsURL("/hello?name=World"))
	defer resp.Body.Close()
	require.Nil(t, err)

	body, err := ioutil.ReadAll(resp.Body)
	require.Nil(t, err)
	assert.Equal(t, "Hello World", string(body))
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetDefaultTLSCert

func SetDefaultTLSCert(cert []byte, key []byte)

SetDefaultTLSCert is used to specify the TLS cert/key used by NewTLS(). Set the params to nil to restore to the internal default (localhost) cert.

func SkipDefaultClientInsecureTLSVerify

func SkipDefaultClientInsecureTLSVerify()

SkipDefaultClientInsecureTLSVerify is a convenience method that sets InsecureSkipVerify to true on http.DefaultClient. This means that you can use insecure certs without receiving an error (assuming your client is using http.DefaultClient).

Types

type Config

type Config struct {
	// Addr is the address to listen on, e.g. ":1234" or "localhost:8080".
	Addr string
	// TLS indicates to start a TLS/HTTPS server.
	TLS bool
	// TLSCert is the TLS certificate to use.
	TLSCert []byte
	// TLSKey is the TLS private key to use.
	TLSKey []byte
}

Config is the options available for staring a techo instance with techo.NewWith().

type Techo

type Techo struct {
	// Port is the port number the server is listening at.
	Port int
	// Base is the base URL (scheme + host + port), e.g. http://127.0.0.1:61241
	URL string
	// Addr provides access to the underlying TCP address object.
	Addr *net.TCPAddr
	*echo.Echo
	// contains filtered or unexported fields
}

Techo is a techo server instance.

func New

func New() *Techo

New starts a server on any available port. This value is available in the Port field. In the unlikely event of an error, the error is logged, and nil is returned.

func NewTLS

func NewTLS() *Techo

NewTLS starts a TLS/HTTPS server on a random port. In the unusual event of an error, the error is logged, and nil is returned.

func NewWith

func NewWith(cfg *Config) (*Techo, error)

NewWith starts a server using the supplied config.

func (*Techo) AbsURL

func (t *Techo) AbsURL(path string) string

AbsURL constructs an absolute URL from the supplied (relative) path. For example, calling te.AbsURL("/my/path") could return "http://127.0.0.1:53262/my/path".

func (*Techo) Stop

func (t *Techo) Stop()

Stop instructs the server to shut down.

func (*Techo) String

func (t *Techo) String() string

Jump to

Keyboard shortcuts

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