***UPDATE:***

Turns out the issue was caused not by testnet, but by having 2 wallets @ryanofsky found out !

----------

Step to reproduce:

This work on regtest just fine:
```
bitcoind -wallet=test -regtest -rpcpassword=abc -rpcuser=abc
```

Try to make a batch RPC request to /wallet/test:

```
[{"jsonrpc":"1.0","id":1,"method":"getbalance","params":["*"]}]
```
You get the expected result.

However; same things with testnet:
```
bitcoind -wallet=test -testnet -rpcpassword=abc -rpcuser=abc
```

Result:

"Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path)."

This problem is limited to batched RPC request on testnet as just making the exact same request without the '[' and ']' works fine. It works also fine on regtest, which is crazy. I will look into later.
{
    if (!timerInterface)
        timerInterface = iface;
}
void RPCSetTimerInterface(RPCTimerInterface *iface)
{
    timerInterface = iface;
}
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
{
    if (timerInterface == iface)
        timerInterface = nullptr;
}
void RPCRunLater(const std::string& name, std::function<void(void)> func, int64_t nSeconds)
{
    if (!timerInterface)
        throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
    deadlineTimers.erase(name);
    LogPrint(BCLog::RPC, "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
    deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)));
}
int RPCSerializationFlags()
{
    int flag = 0;
    if (gArgs.GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) == 0)
        flag |= SERIALIZE_TRANSACTION_NO_WITNESS;
    return flag;
}
CRPCTable tableRPC;